From 42a170aceae71957583ce8791cbb36ac50a937f4 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 19 Jun 2024 11:01:10 +0200 Subject: [PATCH 01/15] Change priority of reserve schedules to 10 (was 0 before) to fix a test Signed-off-by: Daniel Werner --- .../fledge/scheduling-config/model.cid | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid b/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid index c4ced5a..57e8bce 100644 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid +++ b/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid @@ -54,7 +54,7 @@ 1 - DER Scheduler example + ReLevENT reference DER model @@ -352,7 +352,7 @@ - 0 + 10 @@ -472,7 +472,7 @@ - 0 + 10 @@ -588,7 +588,7 @@ - 0 + 10 @@ -1775,4 +1775,4 @@ Alarm - \ No newline at end of file + From 92af59fbec93f697b08236bea5811ea9296b1db7 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 19 Jun 2024 14:47:53 +0200 Subject: [PATCH 02/15] Remove comment Signed-off-by: Daniel Werner --- hedera-61850-gateway/docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/hedera-61850-gateway/docker-compose.yml b/hedera-61850-gateway/docker-compose.yml index 7dc20a7..76674a4 100644 --- a/hedera-61850-gateway/docker-compose.yml +++ b/hedera-61850-gateway/docker-compose.yml @@ -8,8 +8,6 @@ services: build: context: docker-image dockerfile: Dockerfile - # ports: - # - "443:443" volumes: - ./docker-image/hedera-interface.ini:/srv/hedera-61850-gateway/hedera-interface.ini From c5cd61b6989cc6ecf1dee0a830e06c062c69b170 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 19 Jun 2024 14:55:12 +0200 Subject: [PATCH 03/15] Copy conformance tests from der-schduling (https://github.com/alliander-opensource/der-scheduling) to be used as regression tests Signed-off-by: Daniel Werner --- conformance-tests/LICENSE | 202 ++++++ conformance-tests/NOTICE | 18 + conformance-tests/README.md | 49 ++ conformance-tests/allowed-licenses.json | 35 + conformance-tests/build.gradle | 51 ++ conformance-tests/checkLicense.sh | 11 + .../conformance-tests/.gitignore | 2 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + conformance-tests/gradlew | 185 +++++ conformance-tests/gradlew.bat | 89 +++ conformance-tests/licenses/LOGBACK | 11 + conformance-tests/licenses/SLF4J | 21 + conformance-tests/licenses/asn1bean | 202 ++++++ conformance-tests/licenses/commons-io | 203 ++++++ conformance-tests/licenses/iec61850bean | 202 ++++++ conformance-tests/run-all-tests.sh | 3 + conformance-tests/run-demo-tests.sh | 3 + .../utils/annotations/label/Description.java | 25 + .../utils/annotations/label/Requirements.java | 27 + .../org/openmuc/fnn/steuerbox/Context.java | 28 + .../IEC61850MissconfiguredException.java | 23 + .../fnn/steuerbox/IEC61850Utility.java | 469 +++++++++++++ .../fnn/steuerbox/ScheduleWriterExample.java | 111 +++ .../fnn/steuerbox/models/AllianderDER.java | 80 +++ .../fnn/steuerbox/models/Requirement.java | 244 +++++++ .../scheduling/PreparedSchedule.java | 45 ++ .../scheduling/ScheduleDefinitions.java | 79 +++ .../scheduling/ScheduleEnablingErrorKind.java | 44 ++ .../steuerbox/scheduling/ScheduleState.java | 48 ++ .../steuerbox/scheduling/ScheduleType.java | 131 ++++ .../fnn/steuerbox/scheduling/ValueAccess.java | 193 ++++++ .../src/main/resources/logback.xml | 19 + .../fnn/steuerbox/AllianderBaseTest.java | 350 ++++++++++ .../openmuc/fnn/steuerbox/AllianderTests.java | 161 +++++ .../ScheduleControllerNodeTests.java | 188 ++++++ .../fnn/steuerbox/ScheduleExecutionTest.java | 339 ++++++++++ .../fnn/steuerbox/ScheduleNodeTests.java | 634 ++++++++++++++++++ .../openmuc/fnn/steuerbox/UtilityTest.java | 93 +++ .../openmuc/fnn/steuerbox/VersionTest.java | 25 + .../src/test/resources/logback-test.xml | 31 + 41 files changed, 4679 insertions(+) create mode 100644 conformance-tests/LICENSE create mode 100644 conformance-tests/NOTICE create mode 100644 conformance-tests/README.md create mode 100644 conformance-tests/allowed-licenses.json create mode 100755 conformance-tests/build.gradle create mode 100755 conformance-tests/checkLicense.sh create mode 100644 conformance-tests/conformance-tests/.gitignore create mode 100644 conformance-tests/gradle/wrapper/gradle-wrapper.jar create mode 100644 conformance-tests/gradle/wrapper/gradle-wrapper.properties create mode 100755 conformance-tests/gradlew create mode 100644 conformance-tests/gradlew.bat create mode 100644 conformance-tests/licenses/LOGBACK create mode 100644 conformance-tests/licenses/SLF4J create mode 100644 conformance-tests/licenses/asn1bean create mode 100644 conformance-tests/licenses/commons-io create mode 100644 conformance-tests/licenses/iec61850bean create mode 100755 conformance-tests/run-all-tests.sh create mode 100755 conformance-tests/run-demo-tests.sh create mode 100644 conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Description.java create mode 100644 conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Requirements.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850MissconfiguredException.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850Utility.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/Requirement.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleEnablingErrorKind.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleState.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java create mode 100644 conformance-tests/src/main/resources/logback.xml create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java create mode 100644 conformance-tests/src/test/resources/logback-test.xml diff --git a/conformance-tests/LICENSE b/conformance-tests/LICENSE new file mode 100644 index 0000000..9ad0a7b --- /dev/null +++ b/conformance-tests/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 Fraunhofer ISE + + 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. diff --git a/conformance-tests/NOTICE b/conformance-tests/NOTICE new file mode 100644 index 0000000..d4ae3d8 --- /dev/null +++ b/conformance-tests/NOTICE @@ -0,0 +1,18 @@ +Der-scheduling conformance tests +Copyright 2023 Fraunhofer ISE + +This project bundles several dependencies. The project includes: + +- asn1bean without modification. It is distributed under Apache-2.0 license. + The license can be found under licenses/asn1bean. +- iec61850bean without modification. It is distributed under Apache-2.0 license. + The license can be found under licenses/iec61850bean. +- commons-io without modification. It is distributed under Apache-2.0 license. + The license can be found under licenses/commons-io. +- slf4j-api without modification. It is distributed under the MIT license. The license can be found under licenses/SLF4J. +- logback-core without modification. It is distributed under a dual EPL v1.0/LGPL 2.1 license. + It is included into this project under EPL v1.0 The license can be found under licenses/LOGBACK. +- logback-classic without modification. It is distributed under a dual EPL v1.0/LGPL 2.1 license. + It is included into this project under EPL v1.0 The license can be found under licenses/LOGBACK. + +For the exact (maven) references, see build.gradle file under 'dependencies'. diff --git a/conformance-tests/README.md b/conformance-tests/README.md new file mode 100644 index 0000000..883e576 --- /dev/null +++ b/conformance-tests/README.md @@ -0,0 +1,49 @@ +# Alliander rfg+ conformance tests + +This project is aiming for testing the scheduling functions of an existing implementation against +the [requirements](../REQUIREMENTS.md). + +To link the [tests](main/src/test/java/org/openmuc/fnn/steuerbox/) +to their requirements, the requirements are being copied +into [a java class](src/main/java/org/openmuc/fnn/steuerbox/models/Requirement.java) +such that they can be referenced in the javadoc of the tests. A java IDE ( +e.g. [intelliJ](https://www.jetbrains.com/idea/)) will render this in a way that references can be followed +bidirectionally. + +## License + +This test framework is licensed under Apache 2.0 license. It uses dependencies licensed under + +- Eclipse Public license 1.0 +- MIT license +- Apache 2.0 license + +see [NOTICE](NOTICE) for details. + +## Running the tests + +The tests will later on run with JUnit, a common testing framework for java. They can be started by +calling `./gradlew test` for linux systems or `gradlew.bat test` in Windows. + +# Test setup + +Tested runtime environment is openjdk 11. The test assumes the test device is running on localhost (127.0.0.1) and +accessible on port 102. [This is currently hard coded.](test/tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java#L17) + +## Test results + +[Allure](https://github.com/allure-framework) will be used to create readable test reports with more information. + +Also, the testResults folder contains the logs of all tests, these might be useful for debugging. + +## Getting started + +For a first impression, it probably makes sense to have a look in the very +incomplete [requirements](src/main/java/org/openmuc/fnn/steuerbox/models/Requirement.java) +and the +general [IEC 61850 scheduling execution tests](tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java) +, tests on existing IEC 61850 +nodes [of schedule controller](src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java) +and [schedule](src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java) and more +[Alliander spcific tests](main/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java) +. diff --git a/conformance-tests/allowed-licenses.json b/conformance-tests/allowed-licenses.json new file mode 100644 index 0000000..d6a1abb --- /dev/null +++ b/conformance-tests/allowed-licenses.json @@ -0,0 +1,35 @@ +{ + "allowedLicenses": [ + { + "moduleLicense": "The Apache License, Version 2.0", + "moduleVersion": "1.12.0", + "moduleName": "com.beanit:asn1bean" + }, + { + "moduleLicense": "The Apache License, Version 2.0", + "moduleVersion": "1.9.0", + "moduleName": "com.beanit:iec61850bean" + }, + { + "moduleLicense": "Apache License, Version 2.0", + "moduleVersion": "2.11.0", + "moduleName": "commons-io:commons-io" + }, + { + "comment": "MIT can be included into Apache 2.0 according https://www.apache.org/legal/resolved.html#category-a (31.1.23)", + "moduleLicense": "MIT License", + "moduleVersion": "2.0.4", + "moduleName": "org.slf4j:slf4j-api" + }, + { + "comment": "uses dual license, we use Eclipse Public License - v 1.0 which can be included into Apache 2.0 according to https://www.apache.org/legal/resolved.html#category-b (31.1.23)", + "moduleVersion": "1.4.5", + "moduleName": "ch.qos.logback:logback-core" + }, + { + "comment": "uses dual license, we use Eclipse Public License - v 1.0 which can be included into Apache 2.0 according to https://www.apache.org/legal/resolved.html#category-b (31.1.23)", + "moduleVersion": "1.4.5", + "moduleName": "ch.qos.logback:logback-classic" + } + ] +} \ No newline at end of file diff --git a/conformance-tests/build.gradle b/conformance-tests/build.gradle new file mode 100755 index 0000000..ae33596 --- /dev/null +++ b/conformance-tests/build.gradle @@ -0,0 +1,51 @@ +//############################################################################# +//Global configuration +//############################################################################# + + +plugins { + id 'java-library' + id 'com.github.jk1.dependency-license-report' version '2.0' +} +repositories { + mavenCentral() +} +dependencies { + implementation 'ch.qos.logback:logback-classic:1.4.5' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.4' + + implementation group: 'com.beanit', name: 'iec61850bean', version: '1.9.0' + implementation group: 'commons-io', name: 'commons-io', version: '2.11.0' + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.3.1' + +} + +jar { + manifest { + attributes( + 'Main-Class': 'org.openmuc.fnn.steuerbox.ScheduleWriterExample' + ) + } + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +test { + useJUnitPlatform() +} + + +import com.github.jk1.license.render.XmlReportRenderer + +licenseReport { + outputDir = "$projectDir/build/licenses" + configurations = ['runtimeClasspath'] + excludeOwnGroup = true + excludeBoms = false + renderers = [new XmlReportRenderer('third-party-libs.xml', 'Back-End Libraries')] + allowedLicensesFile = new File("$projectDir/allowed-licenses.json") +} \ No newline at end of file diff --git a/conformance-tests/checkLicense.sh b/conformance-tests/checkLicense.sh new file mode 100755 index 0000000..ad5cee3 --- /dev/null +++ b/conformance-tests/checkLicense.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Skript to check proper licensing setup + +./gradlew clean checkLicense + +# check that java files have Apache2.0 license header +APACHE_2_LICENSE="Licensed under the Apache License, Version 2.0" +echo "the following files do not have a proper header:" +find ./ -iname "*.java" -print | xargs grep -L "$APACHE_2_LICENSE" +echo "" diff --git a/conformance-tests/conformance-tests/.gitignore b/conformance-tests/conformance-tests/.gitignore new file mode 100644 index 0000000..ce62f63 --- /dev/null +++ b/conformance-tests/conformance-tests/.gitignore @@ -0,0 +1,2 @@ +.gradle/ +.idea/ diff --git a/conformance-tests/gradle/wrapper/gradle-wrapper.jar b/conformance-tests/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f GIT binary patch literal 59203 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

K7UpUK$>l@ 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 E2O(~oYXATM literal 0 HcmV?d00001 diff --git a/conformance-tests/gradle/wrapper/gradle-wrapper.properties b/conformance-tests/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..f371643 --- /dev/null +++ b/conformance-tests/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/conformance-tests/gradlew b/conformance-tests/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/conformance-tests/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/conformance-tests/gradlew.bat b/conformance-tests/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/conformance-tests/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/conformance-tests/licenses/LOGBACK b/conformance-tests/licenses/LOGBACK new file mode 100644 index 0000000..d349fc0 --- /dev/null +++ b/conformance-tests/licenses/LOGBACK @@ -0,0 +1,11 @@ +Logback: the reliable, generic, fast and flexible logging framework. +Copyright (C) 1999-2022, QOS.ch. All rights reserved. + +This program and the accompanying materials are dual-licensed under +either the terms of the Eclipse Public License v1.0 as published by +the Eclipse Foundation + + or (per the licensee's choosing) + +under the terms of the GNU Lesser General Public License version 2.1 +as published by the Free Software Foundation. \ No newline at end of file diff --git a/conformance-tests/licenses/SLF4J b/conformance-tests/licenses/SLF4J new file mode 100644 index 0000000..d2b54b1 --- /dev/null +++ b/conformance-tests/licenses/SLF4J @@ -0,0 +1,21 @@ +Copyright (c) 2004-2017 QOS.ch + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/conformance-tests/licenses/asn1bean b/conformance-tests/licenses/asn1bean new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/conformance-tests/licenses/asn1bean @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/conformance-tests/licenses/commons-io b/conformance-tests/licenses/commons-io new file mode 100644 index 0000000..6b0b127 --- /dev/null +++ b/conformance-tests/licenses/commons-io @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + diff --git a/conformance-tests/licenses/iec61850bean b/conformance-tests/licenses/iec61850bean new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/conformance-tests/licenses/iec61850bean @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/conformance-tests/run-all-tests.sh b/conformance-tests/run-all-tests.sh new file mode 100755 index 0000000..1d19c1d --- /dev/null +++ b/conformance-tests/run-all-tests.sh @@ -0,0 +1,3 @@ +#!/bin/bash +./gradlew test +echo "All tests run. Please see the logs in testResults/ directory for details" diff --git a/conformance-tests/run-demo-tests.sh b/conformance-tests/run-demo-tests.sh new file mode 100755 index 0000000..18b852b --- /dev/null +++ b/conformance-tests/run-demo-tests.sh @@ -0,0 +1,3 @@ +#!/bin/bash +./gradlew test --tests *ScheduleExecutionTest.test_priorities +echo "Demo tests run. Please see the logs in testResults/ directory for details" diff --git a/conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Description.java b/conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Description.java new file mode 100644 index 0000000..2a96b8e --- /dev/null +++ b/conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Description.java @@ -0,0 +1,25 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package de.fhg.ise.testtool.utils.annotations.label; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Custom Label for test methods to a description + */ +@Target({ ElementType.METHOD }) +public @interface Description { + String value() default ""; +} diff --git a/conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Requirements.java b/conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Requirements.java new file mode 100644 index 0000000..6e7d044 --- /dev/null +++ b/conformance-tests/src/main/java/de/fhg/ise/testtool/utils/annotations/label/Requirements.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package de.fhg.ise.testtool.utils.annotations.label; + +import org.openmuc.fnn.steuerbox.models.Requirement; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Custom Label for test methods to link to requirements + */ +@Target({ ElementType.METHOD }) +public @interface Requirements { + Requirement[] value() default Requirement.NONE; +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java new file mode 100644 index 0000000..0397017 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import javax.xml.parsers.DocumentBuilderFactory; + +/** + * Holds shared objects + */ +public class Context { + + private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + + public static DocumentBuilderFactory getDocumentBuilderFactory() { + return factory; + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850MissconfiguredException.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850MissconfiguredException.java new file mode 100644 index 0000000..4ae7366 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850MissconfiguredException.java @@ -0,0 +1,23 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +/** + * Is thrown if a IEC61850 device is configured in a way that is not expected + */ +public class IEC61850MissconfiguredException extends Exception { + public IEC61850MissconfiguredException(String message) { + super(message); + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850Utility.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850Utility.java new file mode 100644 index 0000000..daa4cfb --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850Utility.java @@ -0,0 +1,469 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import com.beanit.iec61850bean.BasicDataAttribute; +import com.beanit.iec61850bean.BdaBoolean; +import com.beanit.iec61850bean.BdaFloat32; +import com.beanit.iec61850bean.BdaFloat64; +import com.beanit.iec61850bean.BdaInt16; +import com.beanit.iec61850bean.BdaInt16U; +import com.beanit.iec61850bean.BdaInt32; +import com.beanit.iec61850bean.BdaInt32U; +import com.beanit.iec61850bean.BdaInt64; +import com.beanit.iec61850bean.BdaInt8; +import com.beanit.iec61850bean.BdaInt8U; +import com.beanit.iec61850bean.BdaTimestamp; +import com.beanit.iec61850bean.BdaVisibleString; +import com.beanit.iec61850bean.ClientAssociation; +import com.beanit.iec61850bean.ClientSap; +import com.beanit.iec61850bean.Fc; +import com.beanit.iec61850bean.FcModelNode; +import com.beanit.iec61850bean.ModelNode; +import com.beanit.iec61850bean.ServerModel; +import com.beanit.iec61850bean.ServiceError; +import org.apache.commons.io.IOUtils; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule.PreparedScheduleValues; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleEnablingErrorKind; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleState; +import org.openmuc.fnn.steuerbox.scheduling.ValueAccess; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.charset.Charset; +import java.time.Duration; +import java.time.Instant; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +public class IEC61850Utility implements Closeable { + + private final static Logger log = LoggerFactory.getLogger(IEC61850Utility.class); + + private final ClientAssociation association; + private final ServerModel serverModel; + + public ScheduleEnablingErrorKind getSchdEnaErr(String scheduleName) throws ServiceError, IOException { + BasicDataAttribute errorKind = (BasicDataAttribute) serverModel.findModelNode( + scheduleName + ".SchdEnaErr.stVal", null); + association.getDataValues((FcModelNode) errorKind); + return ScheduleEnablingErrorKind.parse(errorKind.getValueString()); + } + + public ScheduleState getScheduleState(String scheduleName) throws ServiceError, IOException { + BasicDataAttribute state = (BasicDataAttribute) serverModel.findModelNode(scheduleName + ".SchdSt.stVal", null); + association.getDataValues((FcModelNode) state); + return ScheduleState.parse(state.getValueString()); + } + + public String getNodeEntryasString(String scheduleName, String specificNode, String dataType) + throws ServiceError, IOException { + BasicDataAttribute nodeEntry = (BasicDataAttribute) serverModel.findModelNode( + scheduleName + "." + specificNode + "." + dataType, null); + association.getDataValues((FcModelNode) nodeEntry); + return nodeEntry.getValueString(); + } + + protected IEC61850Utility(String host, int port) throws UnknownHostException, IOException, ServiceError { + this(InetAddress.getByName(host), port); + } + + protected IEC61850Utility(InetAddress host, int port) throws IOException, ServiceError { + log.info("Connecting to {}:{}", host, port); + ClientSap clientSap = new ClientSap(); + + this.association = clientSap.associate(host, port, null, null); + log.debug("loading server model"); + this.serverModel = this.association.retrieveModel(); + log.debug("done loading server model"); + } + + @Override + public void close() { + this.association.disconnect(); + } + + public static float readConstantSystemReservePowerFromConfigXml(String xml) + throws ParserConfigurationException, IOException, SAXException, IEC61850MissconfiguredException { + DocumentBuilder documentBuilder = Context.getDocumentBuilderFactory().newDocumentBuilder(); + + InputStream asStream = IOUtils.toInputStream(xml, Charset.defaultCharset()); + + Document configDocument = documentBuilder.parse(asStream); + configDocument.getDocumentElement().normalize(); + NodeList reserve = configDocument.getElementsByTagName("reserve"); + + if (reserve.getLength() != 1) { + throw new IEC61850MissconfiguredException( + "Expected to find exactly one element 'reserve' but found: " + reserve + + ". Maybe there is more than one CLS configured?"); + } + + NodeList systemReserveScheduleEntries = reserve.item(0).getChildNodes(); + int valueCount = 0; + String powerAsString = ""; + for (int i = 0; i < systemReserveScheduleEntries.getLength(); i++) { + Node item = systemReserveScheduleEntries.item(i); + // only interested in elements! + if (Node.ELEMENT_NODE == item.getNodeType()) { + valueCount++; + powerAsString = item.getAttributes().getNamedItem("power").getNodeValue(); + } + } + + if (valueCount != 1) { + throw new IEC61850MissconfiguredException( + "Expected exactly 1 power value in system reserve Schedule but got " + + systemReserveScheduleEntries.getLength() + ". Please reconfigure the device."); + } + + float power = Float.parseFloat(powerAsString); + + return power; + } + + /** + * Reads the reserve schedule from the IED's 'config.xml' and returns the constant power. Throws {@link + * IEC61850MissconfiguredException} if the reserve schedule is set up to hold more than one value + */ + public float readConstantPowerFromSysResScheduleFromXML() + throws ParserConfigurationException, IOException, SAXException, IEC61850MissconfiguredException, + ServiceError { + String xml = readFileVia61850("config.xml", 10_000); + System.out.println("XML:\n" + xml); + return readConstantSystemReservePowerFromConfigXml(xml); + } + + /** + * Reads the reserve schedule from the IED Node and returns the constant power. Throws {@link + * IEC61850MissconfiguredException} if the reserve schedule is set up to hold more than one value + */ + public T readConstantValueFromSysResScheduleFromModelNode(ValueAccess valueAccess, + String reserveScheduleName) throws ServiceError, IOException, IEC61850MissconfiguredException { + + // read Number of Entrys + BdaInt32 NumEntrNode = (BdaInt32) serverModel.findModelNode(reserveScheduleName + ".NumEntr.setVal", null); + association.getDataValues(NumEntrNode); + int numEntrValue = NumEntrNode.getValue(); + + //reserve schedule ist just allowed to have one entry, so throw exception if this is not the case + if (numEntrValue != 1) { + throw new IEC61850MissconfiguredException( + "Expected exactly 1 power value in system reserve Schedule but got " + numEntrValue + + ". Please reconfigure the device."); + } + + String valNodeName = valueAccess.getValueAccessString(1, reserveScheduleName); + FcModelNode node = (FcModelNode) serverModel.findModelNode(valNodeName, null); + association.getDataValues(node); + return valueAccess.readToTargetValue(node); + } + + public String readFileVia61850(String fileName, int readTimeoutMillis) throws ServiceError, IOException { + AtomicBoolean done = new AtomicBoolean(false); + StringBuffer buffer = new StringBuffer(); + association.getFile(fileName, (fileData, moreFollows) -> { + + buffer.append(new String(fileData)); + done.set(!moreFollows); + return moreFollows; + }); + + long end = System.currentTimeMillis() + readTimeoutMillis; + while (!done.get()) { + if (System.currentTimeMillis() < end) { + throw new IOException("Timeout exceeded"); + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { + throw new IOException("interrupted", e); + } + } + + return buffer.toString(); + } + + public void writeAndEnableSchedule(PreparedSchedule preparedSchedule) throws ServiceError, IOException { + preparedSchedule.writeAndEnable(this); + } + + public void writeAndEnableSchedule(PreparedScheduleValues values, Duration interval, Instant start, int prio) + throws ServiceError, IOException { + + String scheduleName = writeScheduleValues(values); + + Long intervalInSeconds = interval.getSeconds(); + + if (intervalInSeconds < 1) { + throw new IllegalArgumentException("interval must be larger than one second"); + } + + setDataValues(scheduleName + ".SchdIntv.setVal", null, intervalInSeconds.toString()); + setSchedulePrio(scheduleName, prio); + + setScheduleStart(scheduleName, start); + BasicDataAttribute disableOp = findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp = findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + + operate((FcModelNode) disableOp.getParent().getParent()); + operate((FcModelNode) enableOp.getParent().getParent()); + } + + public void setScheduleStart(String scheduleName, Instant start) throws ServiceError, IOException { + log.info("setting {} start to {}", scheduleName, start); + setDataValues(scheduleName + ".StrTm01.setTm", null, Long.toString(start.toEpochMilli())); + } + + public Instant getScheduleStart(String scheduleName) throws ServiceError, IOException { + BasicDataAttribute schedulePrio = (BasicDataAttribute) serverModel.findModelNode( + scheduleName + ".StrTm01.setTm", null); + association.getDataValues(schedulePrio); + return Instant.parse(schedulePrio.getValueString()); + } + + public void setSchedulePrio(String scheduleName, int prio) throws ServiceError, IOException { + setDataValues(scheduleName + ".SchdPrio.setVal", null, Long.toString(prio)); + } + + public int readSchedulePrio(String scheduleName) throws ServiceError, IOException { + BasicDataAttribute schedulePrio = (BasicDataAttribute) serverModel.findModelNode( + scheduleName + ".SchdPrio.setVal", null); + association.getDataValues(schedulePrio); + return Integer.valueOf(schedulePrio.getValueString()); + } + + /** + * Writes a previously specified Schedule to the device. + */ + public String writeScheduleValues(PreparedScheduleValues values) throws ServiceError, IOException { + String scheduleName = values.getScheduleName(); + + if (values.size() < 1) { + throw new IllegalArgumentException("At least one value required."); + } + + values.writeValues(); + + setDataValues(scheduleName + ".NumEntr.setVal", null, String.valueOf(values.size())); + return scheduleName; + } + + public void disableSchedule(String scheduleNames) throws ServiceError, IOException { + + BasicDataAttribute disableOp = findAndAssignValue(scheduleNames + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + + operate((FcModelNode) disableOp.getParent().getParent()); + } + + protected void operate(FcModelNode node) throws ServiceError, IOException { + try { + association.operate(node); + } catch (ServiceError e) { + throw new ServiceError(e.getErrorCode(), "Unable to operate " + node.getReference().toString(), e); + } + } + + /** + * Reads the main power, that should be controlled by our schedule + */ + public T readGGIOOutput(ScheduleDefinitions constants) throws ServiceError, IOException { + String valueNodeName = constants.getGGIOValueReference(); + ModelNode ggioValue = serverModel.findModelNode(valueNodeName, null); + association.getDataValues((FcModelNode) ggioValue); + ValueAccess valueAccess = constants.getValueAccess(); + T monitoredValue = valueAccess.readToTargetValue((FcModelNode) ggioValue); + log.trace("Got output value '{}' at {} UTC", monitoredValue, Instant.now()); + return monitoredValue; + } + + /** + * Monitors the main power of the 61850 DUT by polling in monitoring interval over the duration of + * monitoringDuration. + *

+ * The result list contains a list of polled values. The first value is the polled value at the start. + */ + public List monitor(Instant start, Duration monitoringDuration, Duration monitoringInterval, + ScheduleDefinitions constants) throws InterruptedException { + + log.info("setting up monitoring"); + if (monitoringDuration.minus(Duration.ofSeconds(1)).isNegative()) { + throw new RuntimeException("Duration is too small, needs to be at least 1s"); + } + + if (start.plus(monitoringDuration).getEpochSecond() < Instant.now().getEpochSecond()) { + throw new RuntimeException("Nothing to monitor, start is in the past"); + } + + AtomicLong counter = new AtomicLong(monitoringDuration.getSeconds() / monitoringInterval.getSeconds()); + + ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1); + + List monitoredValues = new LinkedList<>(); + Runnable monitoringTask = () -> { + try { + if (counter.getAndDecrement() > 0) { + T monitoredValue = readGGIOOutput(constants); + log.debug("Read value '{}' from {}", monitoredValue, constants.getControlledGGIO()); + monitoredValues.add(monitoredValue); + } + else { + service.shutdown(); + } + } catch (ServiceError | IOException e) { + log.error("Unable to read value", e); + } + }; + + long millisUntilStart = Duration.between(Instant.now(), start).toMillis(); + service.scheduleWithFixedDelay(monitoringTask, millisUntilStart, monitoringInterval.toMillis(), + TimeUnit.MILLISECONDS); + + service.awaitTermination(monitoringDuration.getSeconds() + millisUntilStart / 1000 + 5, TimeUnit.SECONDS); + + return monitoredValues; + } + + public BasicDataAttribute setDataValues(String objectReference, Fc fc, String value) + throws ServiceError, IOException { + log.debug("Setting {} to {}", objectReference, value); + BasicDataAttribute bda = findAndAssignValue(objectReference, fc, value); + try { + association.setDataValues(bda); + return bda; + } catch (ServiceError se) { + throw new ServiceError(se.getErrorCode(), + String.format("Unable to set '%s' to '%s'", objectReference, value), se); + } + } + + protected BasicDataAttribute findAndAssignValue(String objectReference, Fc fc, String value) { + ModelNode node = serverModel.findModelNode(objectReference, fc); + if (node == null) { + throw new RuntimeException("Could not find node with name " + objectReference); + } + if (!(node instanceof BasicDataAttribute)) { + throw new RuntimeException( + String.format("Unable to assign a value to node '%s' with type '%s'.", node.getName(), + node.getClass().getSimpleName())); + } + else { + BasicDataAttribute attribute = (BasicDataAttribute) node; + setBda(value, attribute); + return attribute; + } + } + + private static void setBda(String valueString, BasicDataAttribute modelNode) { + if (modelNode instanceof BdaFloat32) { + float value = Float.parseFloat(valueString); + ((BdaFloat32) modelNode).setFloat(value); + } + else if (modelNode instanceof BdaFloat64) { + double value = Float.parseFloat(valueString); + ((BdaFloat64) modelNode).setDouble(value); + } + else if (modelNode instanceof BdaInt8) { + byte value = Byte.parseByte(valueString); + ((BdaInt8) modelNode).setValue(value); + } + else if (modelNode instanceof BdaInt8U) { + short value = Short.parseShort(valueString); + ((BdaInt8U) modelNode).setValue(value); + } + else if (modelNode instanceof BdaInt16) { + short value = Short.parseShort(valueString); + ((BdaInt16) modelNode).setValue(value); + } + else if (modelNode instanceof BdaInt16U) { + int value = Integer.parseInt(valueString); + ((BdaInt16U) modelNode).setValue(value); + } + else if (modelNode instanceof BdaInt32) { + int value = Integer.parseInt(valueString); + ((BdaInt32) modelNode).setValue(value); + } + else if (modelNode instanceof BdaInt32U) { + long value = Long.parseLong(valueString); + ((BdaInt32U) modelNode).setValue(value); + } + else if (modelNode instanceof BdaInt64) { + long value = Long.parseLong(valueString); + ((BdaInt64) modelNode).setValue(value); + } + else if (modelNode instanceof BdaBoolean) { + boolean value = Boolean.parseBoolean(valueString); + ((BdaBoolean) modelNode).setValue(value); + } + else if (modelNode instanceof BdaVisibleString) { + ((BdaVisibleString) modelNode).setValue(valueString); + } + else if (modelNode instanceof BdaTimestamp) { + ((BdaTimestamp) modelNode).setInstant(Instant.ofEpochMilli(Long.parseLong(valueString))); + } + else { + throw new IllegalArgumentException(); + } + } + + public ServerModel getCachedServerModel() { + return serverModel; + } + + /** + * Reads the active schedule reference from the schedule controller + */ + public String readActiveSchedule(String scheduleController) throws ServiceError, IOException { + BdaVisibleString activeSchedule = (BdaVisibleString) serverModel.findModelNode( + scheduleController + ".ActSchdRef.stVal", null); + association.getDataValues((FcModelNode) activeSchedule); + String activeScheduleString = activeSchedule.getValueString(); + log.debug("Got active Schedule {} at {} UTC", activeScheduleString, Instant.now()); + return activeScheduleString; + } + + public void disableSchedules(String scheduleNames) throws ServiceError, IOException { + BasicDataAttribute disableOp = findAndAssignValue(scheduleNames + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + operate((FcModelNode) disableOp.getParent().getParent()); + } + + public boolean nodeExists(String nodeName) { + ModelNode node = getNode(nodeName); + // node is null if it does not exist + return node != null; + } + + public ModelNode getNode(String nodeName) { + return serverModel.findModelNode(nodeName, null); + } + +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java new file mode 100644 index 0000000..025c19b --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java @@ -0,0 +1,111 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import org.openmuc.fnn.steuerbox.models.AllianderDER; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; + +import static java.lang.Integer.parseInt; +import static java.time.Duration.ofSeconds; +import static java.time.Instant.now; +import static java.util.stream.Collectors.toList; + +/** + * Example class to show how modifying schedules works. Not actually relevant for testing, rather intended as an example + * on how to modify schedules. + */ +public class ScheduleWriterExample { + + public static final String HOST_NAME = "192.168.17.200"; + + private static Logger log = LoggerFactory.getLogger(ScheduleWriterExample.class); + + public static void main(String[] args) { + final Instant setupStart = now(); + final List argList = Arrays.asList(args); + try { + final Duration interval = ofSeconds(5); + log.info("Got args {}", argList); + + if (argList.size() < 4) { + throw new IllegalArgumentException("Too few arguments"); + } + + final int schedule_number = parseInt(argList.get(0)); + final int seconds = parseInt(argList.get(1)); + final Instant start = now().plusSeconds(seconds); + final int prio = parseInt(argList.get(2)); + final List values = argList.stream()// + .skip(3)// + .map(Integer::parseInt)// + .collect(toList()); + + if (seconds < 1) { + throw new IllegalArgumentException("Seconds " + seconds + " needs to be at last 1"); + } + + if (schedule_number < 1 || schedule_number > 10) { + throw new IllegalArgumentException( + "Illegal schedule number " + schedule_number + " needs to be between 1 and 10"); + } + + if (prio < 10) { + throw new IllegalArgumentException("Prio " + prio + "too low: needs to be equal to or larger than 10"); + } + + log.info("Setting up new schedule with prio {} starting at {} with interval {} and values {}", prio, start, + interval, values); + + try (final AllianderDER allianderDER = new AllianderDER(HOST_NAME, 102)) { + PreparedSchedule preparedSchedule = allianderDER.maxPowerSchedules.prepareSchedule(values, + schedule_number, interval, start, prio); + allianderDER.writeAndEnableSchedule(preparedSchedule); + + } catch (Exception e) { + throw new ScheduleEnableException(e); + } + log.info("SUCCESS! Set up schedule in {}", Duration.between(setupStart, Instant.now())); + log.info("Schedule will start running in {} (IN CASE THE CLOCK OF THE DEVICE IS SET UP PROPERLY)", + Duration.between(now(), start)); + } catch (ScheduleEnableException e) { + log.error("Execution occured while setting up schedule", e.cause); + log.error("Unable to activate schedule, exiting"); + System.exit(1); + } catch (Exception e) { + String explantion = "(schedule number [1-10]) (seconds until start > 1) (prio > 10) (value1 value2 value3)"; + String example = "1 30 42 0 10 20 30 40"; + log.error("Unable to parse input args '{}', failed with {}: {}", argList, e.getClass(), e.getMessage()); + log.info("Arguments '{}' could not be parsed (see above).", argList); + log.info("Expecting something like '{}'", example); + log.info("or at least like '{}'", "1 0 11 42"); + log.info("where '{}'.", explantion); + System.exit(2); + } + } + + static class ScheduleEnableException extends Exception { + final Exception cause; + + public ScheduleEnableException(Exception cause) { + this.cause = cause; + } + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java new file mode 100644 index 0000000..46ed17b --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java @@ -0,0 +1,80 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox.models; + +import com.beanit.iec61850bean.ServiceError; +import org.openmuc.fnn.steuerbox.IEC61850Utility; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleType; + +import java.io.IOException; + +public class AllianderDER extends IEC61850Utility { + + public AllianderDER(String host, int port) throws ServiceError, IOException { + super(host, port); + } + + public static AllianderDER getWithDefaultSettings() throws ServiceError, IOException { + return new AllianderDER("127.0.0.1", 102); + } + + public final ScheduleDefinitions powerSchedules = ScheduleType.ASG.withScheduleDefinitions(this, + "active power schedules",// + "DER_Scheduler_Control/ActPow_GGIO1",// + "DER_Scheduler_Control/ActPow_FSCC1",// + "DER_Scheduler_Control/ActPow_Res_FSCH01",// + "DER_Scheduler_Control/ActPow_FSCH01", // + "DER_Scheduler_Control/ActPow_FSCH02", // + "DER_Scheduler_Control/ActPow_FSCH03", // + "DER_Scheduler_Control/ActPow_FSCH04", // + "DER_Scheduler_Control/ActPow_FSCH05", // + "DER_Scheduler_Control/ActPow_FSCH06", // + "DER_Scheduler_Control/ActPow_FSCH07", // + "DER_Scheduler_Control/ActPow_FSCH08", // + "DER_Scheduler_Control/ActPow_FSCH09", // + "DER_Scheduler_Control/ActPow_FSCH10"); + + public final ScheduleDefinitions maxPowerSchedules = ScheduleType.ASG.withScheduleDefinitions(this, + "max power schedules",// + "DER_Scheduler_Control/MaxPow_GGIO1",// + "DER_Scheduler_Control/MaxPow_FSCC1",// + "DER_Scheduler_Control/MaxPow_Res_FSCH01",// + "DER_Scheduler_Control/MaxPow_FSCH01", // + "DER_Scheduler_Control/MaxPow_FSCH02", // + "DER_Scheduler_Control/MaxPow_FSCH03", // + "DER_Scheduler_Control/MaxPow_FSCH04", // + "DER_Scheduler_Control/MaxPow_FSCH05", // + "DER_Scheduler_Control/MaxPow_FSCH06", // + "DER_Scheduler_Control/MaxPow_FSCH07", // + "DER_Scheduler_Control/MaxPow_FSCH08", // + "DER_Scheduler_Control/MaxPow_FSCH09", // + "DER_Scheduler_Control/MaxPow_FSCH10"); + + public final ScheduleDefinitions onOffSchedules = ScheduleType.SPG.withScheduleDefinitions(this, + "on/off schedules",// + "DER_Scheduler_Control/OnOff_GGIO1",// + "DER_Scheduler_Control/OnOff_FSCC1",// + "DER_Scheduler_Control/OnOff_Res_FSCH01",// + "DER_Scheduler_Control/OnOff_FSCH01", // + "DER_Scheduler_Control/OnOff_FSCH02", // + "DER_Scheduler_Control/OnOff_FSCH03", // + "DER_Scheduler_Control/OnOff_FSCH04", // + "DER_Scheduler_Control/OnOff_FSCH05", // + "DER_Scheduler_Control/OnOff_FSCH06", // + "DER_Scheduler_Control/OnOff_FSCH07", // + "DER_Scheduler_Control/OnOff_FSCH08", // + "DER_Scheduler_Control/OnOff_FSCH09", // + "DER_Scheduler_Control/OnOff_FSCH10"); +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/Requirement.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/Requirement.java new file mode 100644 index 0000000..7da0a69 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/Requirement.java @@ -0,0 +1,244 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + + +package org.openmuc.fnn.steuerbox.models; + +/** + * These requirements are meant to be linked from the JavaDoc of unit tests covering them. This way, requirements + * *should* be linked easily to their tests and vice versa. + *

+ * All requirements are taken from the main github at https://github.com/alliander-opensource/der-scheduling/blob/main/REQUIREMENTS.md + * . + *

+ * Adding the description as JavaDoc helps to quickly identify what a requirement stands for. + */ +public enum Requirement { + + /** + * Just a placeholder + */ + NONE, + + // CONFIGURATION + + /** + * Basic configuration of DER default shall be stored inside a SCL File + */ + C01, + + /** + * Reserve schedules shall be stored inside a SCL File + */ + C01a, + + /** + * Number of available schedules (maximum 10 schedules per logical Node, less can be configured) shall be stored + * inside a SCL File + */ + C01b, + + /** + * Number of devices to be controlled (limited to 1 for evaluation, extension shall be foreseen) shall be stored + * inside a SCL File + */ + C01c, + + /** + * Parameters of schedules other than the reserve schedule are to be stored in a key-value manner + */ + C02, + + /** + * Parameters of schedules other than the reserve schedule are persisted to a separate file (e.g. as JSON) + */ + C03, + + /** + * Changes in schedules are persisted into the file as soon as the schedule is validated + */ + C04, + + /** + * A interface to CoMPAS is not required. + */ + C05, + + /** + * A simple interface to notify about changes in SCL file is to be defined. + */ + C05a, + + /** + * A simple interface to notify about changes in key-value + */ + C05b, + + // LOGICAL NODES + + /** + * Map Logical Nodes and Common Data Classes to configuration values, allow reading and writing according to + * 61850-90-10 + */ + LN01, + + /** + * The control functions of the DER are modeled and implemented independently + */ + LN02, + + /** + * Absolute active power is controlled in 10 logical nodes ActPow_FSCH01 .. ActPow_FSCH10, with schedule controller + * ActPow_FSCC1 and actuator interface ActPow_GGIO1 + */ + LN02a, + + /** + * Maximum power is controlled in 10 logical nodes MaxPow_FSCH01 .. MaxPow_FSCH10, with schedule controller + * MaxPow_FSCC1 and actuator interface MaxPow_GGIO1 + */ + LN02b, + + /** + * On/Off state of the DER is controlled 10 logical nodes OnOff_FSCH01 .. OnOff_FSCH10, with schedule controller + * OnOff_FSCC1 and actuator interface OnOff_GGIO1 + */ + LN02c, + + /** + * The scheduling nodes and their children are to be modeled according to 61850-90-10 + */ + LN03, + + // SCHEDULING + + /** + * A set of 10 schedules per logical node must be supported + */ + S01, + + /** + * Support time based schedules + */ + S02, + + /** + * Triggers other than time based may be supported + */ + S03, + + /** + * Periodical schedules must be supported + */ + S04, + + /** + * Support of absolute schedules of absolute power setpoints + */ + S05a, + + /** + * Support of absolute schedules of maximum power setpoints + */ + S05b, + + /** + * Support of schedules to turn DER on and off + */ + S05c, + + /** + * Validation of Schedules according to 61850-90-10 + */ + S08, + + /** + * Schedules for maximum generation values and absolute power values are modeled in the same way (using the same + * DTO) + */ + S09, + + /** + * Each schedule must store a sequence of max. 100 values + */ + S10, + + /** + * There are three Reserve Schedules: Active Power Reserve Schedule, Maximum Power Reserve Schedule and On/Off + * Reserve Schedule + */ + S11, + + /** + * Each Reserve Schedule holds 100 values + */ + S12, + + /** + * Reserve Schedules are always active and cannot be deactivated + */ + S13, + + /** + * Reserve Schedules have the lowest priority (10). This cannot be changed. + */ + S14, + + /** + * Reserve Schedules have a fixed start date of 01.01.1970 00:00:01 (UTC). This cannot be changed. + */ + S15, + + /** + * Reserve Schedules are set to cyclic execution. This cannot be changed. + */ + S16, + + /** + * If two schedules are configured with the same pirority and start time, the schedule that comes first in the + * schedule controller's schedule reference is executed. + */ + S17, + + // SCHEDULE EXECUTION + + /** + * Execution of schedules must regard schedule priority according to 61850-10 + */ + E01, + + /** + * Resolution time base: >= 1 second + */ + E02, + + // INTERFACES + + /** + * The Active power Actuator Interface contains the current value (a double) and the source schedule priority (an + * integer) + */ + I01, + + /** + * The Maximum Power Actuator Interface contains the current value (a double) and the source schedule priority (an + * integer) + */ + I02, + + /** + * The On/Off Actuator Interface contains the current value (a double) and the source schedule priority (an + * integer). The mapping is 0 - off / 1 - on. + */ + I03; +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java new file mode 100644 index 0000000..4e059d6 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox.scheduling; + +import com.beanit.iec61850bean.ServiceError; +import org.openmuc.fnn.steuerbox.IEC61850Utility; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; + +/** + * A schedule, ready to be written to the IEC 61850 device + */ +public interface PreparedSchedule { + /** + * Writes and enables the schedule on the device + */ + void writeAndEnable(IEC61850Utility utility) throws ServiceError, IOException; + + /** + * Representation of schedule values ready to be written to the 61850 server. Implementations of {@link + * PreparedScheduleValues} are available in {@link ValueAccess}. + */ + interface PreparedScheduleValues { + void writeValues() throws ServiceError, IOException; + + int size(); + + String getScheduleName(); + + PreparedSchedule asSchedule(Duration interval, Instant start, int prio); + } +} \ No newline at end of file diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java new file mode 100644 index 0000000..41a0268 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java @@ -0,0 +1,79 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox.scheduling; + +import java.time.Duration; +import java.time.Instant; +import java.util.Collection; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Contains 61850 references to essential nodes of a schedule + */ +public interface ScheduleDefinitions { + + /** + * Returns access to schedule values such that these can be modified on the 61850 device + */ + ValueAccess getValueAccess(); + + /** + * Prepare a schedule to be + */ + default PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, Instant start, + int prio) { + ValueAccess valueAccess = getValueAccess(); + return valueAccess.prepareSchedule(values, scheduleNumber, interval, start, prio); + } + + /** + * Get the schedule name from the number + * + * @throws IllegalArgumentException + * if no schedule with that number is known + */ + String getScheduleName(int scheduleNumber) throws IllegalArgumentException; + + /** + * Get the number of a schedule from its name. + * + * @throws IllegalArgumentException + * if no scheudle with that name is known + */ + int getScheduleNumber(String scheduleName) throws IllegalArgumentException; + + String getControlledGGIO(); + + String getGGIOValueReference(); + + String getController(); + + String getReserveSchedule(); + + Collection getAllScheduleNames(); + + ScheduleType getScheduleType(); + + T getDefaultValue(); + + default Collection getDefaultValues(int numberOfValues) { + if (numberOfValues < 1) { + throw new IllegalArgumentException( + "numberOfValues (the size of the returned collection) needs to be at least 1"); + } + final T defaultValue = getDefaultValue(); + return Stream.generate(() -> defaultValue).limit(numberOfValues).collect(Collectors.toList()); + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleEnablingErrorKind.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleEnablingErrorKind.java new file mode 100644 index 0000000..fcd1ef8 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleEnablingErrorKind.java @@ -0,0 +1,44 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox.scheduling; + +/** + * Representation of error codes ("ScheduleEnablingErrorKind") defined in IEC61850-90-10 ed 2017, Table 9 (page 28) + */ +public enum ScheduleEnablingErrorKind { + NONE(1), + MISSING_VALID_NUMENTR(2), + MISSING_VALID_SCHDINTV(3), + MISSING_VALID_SCHEDULE_VALUES(4); + + private final int value; + + ScheduleEnablingErrorKind(int value) { + this.value = value; + } + + public static ScheduleEnablingErrorKind parse(String valueString) { + try { + Integer value = Integer.parseInt(valueString); + for (ScheduleEnablingErrorKind errorKind : ScheduleEnablingErrorKind.values()) { + if (errorKind.value == value) { + return errorKind; + } + } + } catch (Exception e) { + return NONE; + } + return NONE; + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleState.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleState.java new file mode 100644 index 0000000..fa60252 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleState.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox.scheduling; + +/** + * Schedule states defined in IEC61850-90-10 ed 2017, Table 8 (page 28) + */ +public enum ScheduleState { + /** + * Fallback state for error cases + */ + UNKNOWN(0), + NOT_READY(1), + START_TIME_REQUIRED(2), + READY(3), + RUNNING(4); + + private final int value; + + private ScheduleState(int value) { + this.value = value; + } + + public static ScheduleState parse(String valueString) { + try { + Integer value = Integer.parseInt(valueString); + for (ScheduleState state : ScheduleState.values()) { + if (state.value == value) { + return state; + } + } + } catch (Exception e) { + return UNKNOWN; + } + return UNKNOWN; + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java new file mode 100644 index 0000000..e9170a0 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java @@ -0,0 +1,131 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox.scheduling; + +import org.openmuc.fnn.steuerbox.IEC61850Utility; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.function.BiFunction; + +/** + * Represents different types of schedules regarding the values they represent, or in other words what type of GGIO (for + * now analogue values, boolean values) they control. + */ +public enum ScheduleType { + /** + * Used to schedule analogue values (that are mapped as floats) such as power schedules + */ + ASG((device, schedule) -> ValueAccess.asgAccess(device, schedule)) { + @Override + public ScheduleDefinitions withScheduleDefinitions(IEC61850Utility device, String displayName, + String ggio, String controller, String reserveSchedule, String... schedules) { + return ASG.createScheduleDefinitionsFrom(device, displayName, ggio, controller, reserveSchedule, 0f, + schedules); + } + }, + /** + * Used to schedule boolean values, such as OnOff schedules + */ + SPG((device, schedule) -> ValueAccess.spgAccess(device, schedule)) { + @Override + public ScheduleDefinitions withScheduleDefinitions(IEC61850Utility device, String displayName, + String ggio, String controller, String reserveSchedule, String... schedules) { + return SPG.createScheduleDefinitionsFrom(device, displayName, ggio, controller, reserveSchedule, false, + schedules); + } + }; + + private BiFunction valueAccessFunction; + + ScheduleType(BiFunction valueAccessFunction) { + this.valueAccessFunction = valueAccessFunction; + } + + public abstract ScheduleDefinitions withScheduleDefinitions(IEC61850Utility device, String displayName, + String ggio, String controller, String reserveSchedule, String... schedules); + + private ScheduleDefinitions createScheduleDefinitionsFrom(IEC61850Utility device, String displayName, + String ggio, String controller, String reserveSchedule, T defaultValue, String... schedules) { + + List scheduleNames = Arrays.asList(schedules); + + return new ScheduleDefinitions() { + @Override + public String getScheduleName(int scheduleNumber) { + if (scheduleNumber <= 0 || scheduleNumber > scheduleNames.size()) { + throw new IllegalArgumentException("Schedule number must be between 1 and " + scheduleNames.size()); + } + return scheduleNames.get(scheduleNumber - 1); + } + + @Override + public int getScheduleNumber(String scheduleName) throws IllegalArgumentException { + for (int i = 0; i < scheduleNames.size(); i++) { + if (scheduleNames.get(i).equals(scheduleName)) { + int scheduleNumber = i + 1; + return scheduleNumber; + } + } + throw new IllegalArgumentException("No schedule with name '" + scheduleName + "' configured"); + } + + @Override + public String getControlledGGIO() { + return ggio; + } + + @Override + public String getGGIOValueReference() { + return getControlledGGIO() + getValueAccess().getGGIOValueSuffix(); + } + + @Override + public Collection getAllScheduleNames() { + return scheduleNames; + } + + @Override + public ValueAccess getValueAccess() { + return valueAccessFunction.apply(device, this); + } + + @Override + public org.openmuc.fnn.steuerbox.scheduling.ScheduleType getScheduleType() { + return org.openmuc.fnn.steuerbox.scheduling.ScheduleType.this; + } + + @Override + public T getDefaultValue() { + return defaultValue; + } + + @Override + public String getController() { + return controller; + } + + @Override + public String getReserveSchedule() { + return reserveSchedule; + } + + @Override + public String toString() { + return displayName; + } + }; + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java new file mode 100644 index 0000000..d918a5e --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java @@ -0,0 +1,193 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox.scheduling; + +import com.beanit.iec61850bean.BdaBoolean; +import com.beanit.iec61850bean.BdaFloat32; +import com.beanit.iec61850bean.FcModelNode; +import com.beanit.iec61850bean.ServiceError; +import org.openmuc.fnn.steuerbox.IEC61850Utility; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.Collection; + +/** + * Provides access to the Values that are stored inside a ScheduleDefinition. This access is using generics to support + * differrent {@link ScheduleType}s. + */ +public interface ValueAccess { + + String getValueAccessString(int valueIndex, String scheduleName); + + String getGGIOValueSuffix(); + + PreparedSchedule.PreparedScheduleValues prepareWriting(Collection values, String scheduleName); + + default PreparedSchedule.PreparedScheduleValues prepareWriting(T singleValue, String scheduleName) { + return prepareWriting(Arrays.asList(singleValue), scheduleName); + } + + PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, Instant start, + int prio); + + /** + * Write a default value to this schedule. Useful if several types of schedules are to be processed. + */ + PreparedSchedule.PreparedScheduleValues activateScheduleWithDefaultValue(String scheduleName); + + T readToTargetValue(FcModelNode node) throws ServiceError, IOException; + + private static PreparedSchedule valueWriterToScheduleWriter(PreparedSchedule.PreparedScheduleValues vw, + Duration interval, Instant start, int prio) { + return utility -> utility.writeAndEnableSchedule(vw, interval, start, prio); + } + + static ValueAccess asgAccess(IEC61850Utility utility, ScheduleDefinitions schedule) { + + Logger log = LoggerFactory.getLogger(ValueAccess.class.getName() + ".asgAccess"); + + return new ValueAccess() { + + @Override + public String getValueAccessString(int valueIndex, String scheduleName) { + return String.format("%s.ValASG%03d.setMag.f", scheduleName, valueIndex); + } + + @Override + public String getGGIOValueSuffix() { + return ".AnOut1.mxVal.f"; + } + + @Override + public PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, + Instant start, int prio) { + return prepareWriting(values, schedule.getScheduleName(scheduleNumber)).asSchedule(interval, start, + prio); + } + + @Override + public PreparedSchedule.PreparedScheduleValues prepareWriting(Collection values, + String scheduleName) { + return new PreparedSchedule.PreparedScheduleValues() { + @Override + public void writeValues() throws ServiceError, IOException { + int index = 1; + for (Number value : values) { + String valueBasicDataAttribute = getValueAccessString(index++, scheduleName); + log.debug("Writing {} to {}", value, valueBasicDataAttribute); + utility.setDataValues(valueBasicDataAttribute, null, value.toString()); + } + } + + @Override + public int size() { + return values.size(); + } + + @Override + public String getScheduleName() { + return scheduleName; + } + + @Override + public PreparedSchedule asSchedule(Duration interval, Instant start, int prio) { + return valueWriterToScheduleWriter(this, interval, start, prio); + } + }; + } + + @Override + public PreparedSchedule.PreparedScheduleValues activateScheduleWithDefaultValue(String scheduleName) { + return prepareWriting(Arrays.asList(0), scheduleName); + } + + @Override + public Number readToTargetValue(FcModelNode node) throws ServiceError, IOException { + return ((BdaFloat32) node).getFloat(); + } + + }; + } + + static ValueAccess spgAccess(IEC61850Utility utility, ScheduleDefinitions schedules) { + + Logger log = LoggerFactory.getLogger(ValueAccess.class.getName() + ".spgAccess"); + + return new ValueAccess() { + @Override + public String getValueAccessString(int valueIndex, String scheduleName) { + return String.format("%s.ValSPG%03d.setVal", scheduleName, valueIndex); + } + + @Override + public String getGGIOValueSuffix() { + return ".SPCSO1.stVal"; + } + + @Override + public PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, + Instant start, int prio) { + return prepareWriting(values, schedules.getScheduleName(scheduleNumber)).asSchedule(interval, start, + prio); + } + + @Override + public PreparedSchedule.PreparedScheduleValues prepareWriting(Collection values, + String scheduleName) { + return new PreparedSchedule.PreparedScheduleValues() { + @Override + public void writeValues() throws ServiceError, IOException { + int index = 1; + for (Boolean value : values) { + String valueBasicDataAttribute = getValueAccessString(index++, scheduleName); + log.debug("Writing {} to {}", value, valueBasicDataAttribute); + utility.setDataValues(valueBasicDataAttribute, null, value.toString()); + } + } + + @Override + public int size() { + return values.size(); + } + + @Override + public String getScheduleName() { + return scheduleName; + } + + @Override + public PreparedSchedule asSchedule(Duration interval, Instant start, int prio) { + return valueWriterToScheduleWriter(this, interval, start, prio); + } + }; + } + + @Override + public PreparedSchedule.PreparedScheduleValues activateScheduleWithDefaultValue(String scheduleName) { + return prepareWriting(Arrays.asList(false), scheduleName); + } + + @Override + public Boolean readToTargetValue(FcModelNode node) throws ServiceError, IOException { + return ((BdaBoolean) node).getValue(); + } + }; + } + +} diff --git a/conformance-tests/src/main/resources/logback.xml b/conformance-tests/src/main/resources/logback.xml new file mode 100644 index 0000000..aba86f9 --- /dev/null +++ b/conformance-tests/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + \ No newline at end of file diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java new file mode 100644 index 0000000..f3090cb --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java @@ -0,0 +1,350 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import com.beanit.iec61850bean.Fc; +import com.beanit.iec61850bean.FcModelNode; +import com.beanit.iec61850bean.ModelNode; +import com.beanit.iec61850bean.ObjectReference; +import com.beanit.iec61850bean.ServiceError; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.openmuc.fnn.steuerbox.models.AllianderDER; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Common fields and methods for 61850 testing + */ +public abstract class AllianderBaseTest { + + private static final Logger logger = LoggerFactory.getLogger(ScheduleNodeTests.class); + + protected static AllianderDER dut; + + @BeforeAll + public static void connectToDUT() throws ServiceError, IOException { + dut = AllianderDER.getWithDefaultSettings(); + } + + @BeforeEach + public void stopAllRunningSchedules(){ + disableAllRunningSchedules(); + logger.debug("Disabled all schedules during init"); + } + + @AfterAll + public static void shutdownConnection() { + dut.close(); + } + + public static void disableAllRunningSchedules() { + getAllSchedules().forEach(scheduleType -> { + scheduleType.getAllScheduleNames().forEach(schedule -> { + try { + dut.disableSchedules(schedule); + } catch (Exception e) { + Assertions.fail("error, could not disable schedule " + schedule); + logger.error("error, could not disable schedule " + schedule, e); + } + }); + }); + } + + /** + * These schedules use float values for scheduling + */ + protected static Stream> getPowerValueSchedules() { + return getAllSchedules().filter(s -> ScheduleType.ASG == s.getScheduleType()); + } + + /** + * These schedules use boolean values for scheduling + */ + protected static Stream> getOnOffSchedules() { + return getAllSchedules().filter(s -> ScheduleType.SPG == s.getScheduleType()); + } + + protected static Stream> getAllSchedules() { + return Stream.of(dut.powerSchedules, dut.maxPowerSchedules, dut.onOffSchedules); + } + + public static void assertValuesMatch(List expectedValues, List actualValues, double withPercentage) { + Assertions.assertEquals(actualValues.size(), expectedValues.size()); + for (int i = 0; i < expectedValues.size(); i++) { + Float expected = expectedValues.get(i); + Float actual = actualValues.get(i); + Assertions.assertEquals(expected, actual,withPercentage,"Array does not match at index "+i+". " + + "\nExpected values: "+expectedValues+"" + + "\nactual values : "+actualValues+"\n"); + } + } + + private static boolean areClose(Float actual, Float expected, double withPercentage) { + double lowerBound = expected * (1.0 - withPercentage / 100f); + double upperBound = expected * (1.0 + withPercentage / 100f); + return actual >= lowerBound && actual <= upperBound; + } + + public static void assertValuesMatch(List expectedValues, List actualValues) { + Assertions.assertEquals(actualValues.size(), expectedValues.size()); + for (int i = 0; i < expectedValues.size(); i++) { + boolean expected = expectedValues.get(i); + boolean actual = actualValues.get(i); + Assertions.assertEquals(expected, actual,"Array does not match at index "+i+". " + + "\nExpected values: "+expectedValues+"" + + "\nactual values : "+actualValues+"\n"); + } + } + + + protected void assertUntypedValuesMatch(List expectedValues, List actualValues) { + if(expectedValues.size() <= 0){ + if(expectedValues.size() == 0 && actualValues.size()==0){ + + } + else { + Assertions.fail("Values do not match, different array sizes. Expected "+expectedValues.size()+" but got "+actualValues.size()); + } + } + if (Float.class.equals(expectedValues.get(0).getClass())) { + assertValuesMatch((List) expectedValues, (List) actualValues,0.1); + } + else if (Boolean.class.equals(expectedValues.get(0).getClass())) { + assertValuesMatch((List) expectedValues, (List) actualValues); + }else { + throw new IllegalArgumentException("Expected Float or Boolean, got:"+expectedValues.get(0).getClass()); + } + } + + protected Collection testMandatoryNodes(Map mandatory, String parentNode) { + Collection violations = new LinkedList<>(); + + for (Map.Entry entry : mandatory.entrySet()) { + String fullNodeName = parentNode + "." + entry.getKey(); + + if (dut.nodeExists(fullNodeName)) { + ModelNode node = dut.getNode(fullNodeName); + + Fc actualFc = ((FcModelNode) node).getFc(); + if (!Objects.equals(entry.getValue(), actualFc)) { + violations.add("Mandatory requirement: node " + entry.getKey() + " is not the expected type " + + entry.getValue() + " but instead " + actualFc); + } + } + else { + violations.add("Mandatory requirement: node" + fullNodeName + "is not present"); + } + } + return violations; + } + + protected Collection testAtMostOnceNodes(Map atMostOne, String parentNode) { + + Collection violations = new LinkedList<>(); + + for (Map.Entry entry : atMostOne.entrySet()) { + ModelNode scheduleNode = dut.getNode(parentNode); + if (scheduleNode == null) { + Assertions.fail("Unable to find node " + parentNode); + } + List occurencesThatContainKeyInName = scheduleNode.getChildren().stream()// + .filter(childNode -> childNode.getName().contains(entry.getKey()))// + .map(ModelNode::getReference)// + .map(ObjectReference::toString)// in order for distinct to work, ObjectReference does not implement equals() nor hashCode() + .distinct()// + .collect(Collectors.toList()); + + if (occurencesThatContainKeyInName.size() > 1) { + violations.add("atMostOnce requirement: Expected at most 1 occurence of nodes with '" + entry.getKey() + + "' in their name but found" + occurencesThatContainKeyInName.size() + ": " + + occurencesThatContainKeyInName); + } + } + return violations; + } + + protected Collection testOMulti(Map oMulti, String parentNode) { + Collection violations = new LinkedList<>(); + + for (Map.Entry entry : oMulti.entrySet()) { + List occurencesThatContainKeyInName = dut.getNode(parentNode) + .getChildren() + .stream()// + .filter(childNode -> childNode.getName().contains(entry.getKey()))// + .filter(childNode -> entry.getKey().equals(removeNumbers(childNode.getName()))) + .collect(Collectors.toList()); + + for (ModelNode foundOptionalNode : occurencesThatContainKeyInName) { + Fc actualFc = ((FcModelNode) foundOptionalNode).getFc(); + + if (!Objects.equals(entry.getValue(), actualFc)) { + violations.add("Omulti requirement: Node " + foundOptionalNode.getReference() + + " does not have expected type " + entry.getValue() + " but instead " + actualFc); + } + + Optional number = extractNumberFromLastNodeName(foundOptionalNode.getName()); + if (number.isEmpty()) { + violations.add( + "Omulti requirement: Expected a instance number in node " + foundOptionalNode.getReference() + + " but found none."); + } + else if (number.get() < 1) { + violations.add("Omulti requirement: Expected a instance number larger than 0 but found " + number + + " in Omulti node " + foundOptionalNode.getReference()); + } + } + } + return violations; + } + + public static String removeNumbers(String stringWithNumbers) { + if (stringWithNumbers == null) { + return null; + } + return stringWithNumbers.replaceAll("[0-9]", ""); + } + + protected Collection testMMulti(Map mMulti, String parentNode) { + Collection violations = new LinkedList<>(); + + for (Map.Entry entry : mMulti.entrySet()) { + List occurencesThatContainKeyInName = dut.getNode(parentNode) + .getChildren() + .stream()// + .filter(childNode -> childNode.getName().contains(entry.getKey()))// + .filter(childNode -> childNode instanceof FcModelNode) + .map(childNode -> (FcModelNode) childNode) + .collect(Collectors.toList()); + + if (occurencesThatContainKeyInName.isEmpty()) { + violations.add("Mmulti requirement: Expected a node that contains " + entry.getKey() + + " in its name but found none for parent " + parentNode); + continue; // just to make this clear, the further for loop will not be executed anyways... + } + + for (ModelNode foundOptionalNode : occurencesThatContainKeyInName) { + Fc actualFc = ((FcModelNode) foundOptionalNode).getFc(); + if (!Objects.equals(entry.getValue(), actualFc)) { + violations.add("Mmulti requirement: Node " + foundOptionalNode.getReference() + + " does not have expected type " + entry.getValue() + " but instead " + actualFc); + } + + Optional number = extractNumberFromLastNodeName(foundOptionalNode.getName()); + if (number.isEmpty()) { + violations.add( + "Omulti requirement: Expected a instance number in node " + foundOptionalNode.getReference() + + " but found none."); + } + else if (number.get() < 1) { + violations.add("Omulti requirement: Expected a instance number larger than 0 but found " + number + + " in Omulti node " + foundOptionalNode.getReference()); + } + } + } + return violations; + } + + public static Optional extractNumberFromLastNodeName(String foundNodeName) { + try { + String[] split = foundNodeName.split("\\."); + + String lastElement = foundNodeName; + if (split.length > 0) { + lastElement = split[split.length - 1]; + } + String numberAsString = lastElement.replaceAll("[^0-9]", ""); + return Optional.of(Integer.parseInt(numberAsString)); + } catch (Exception e) { + return Optional.empty(); + } + } + + protected Collection testMMultiF(Collection mMultiF, + String parentNode) { + Collection violations = new LinkedList<>(); + + for (AllianderTests.MandatoryOnCondition mandatoryOnCondition : mMultiF) { + String conditionNode = parentNode + mandatoryOnCondition.condition; + if (dut.nodeExists(conditionNode)) { + + String nowMandatoryNode = parentNode + mandatoryOnCondition.mandatoryOnCondition; + if (!dut.nodeExists(nowMandatoryNode)) { + violations.add("Node " + nowMandatoryNode + " is not present though it is required because node " + + conditionNode + " is present"); + } + } + else { + // condition not met, nothing more to check + } + } + return violations; + } + + protected Collection testOptionalNodes(Map optional, String parentNode) { + Collection violations = new LinkedList<>(); + for (Map.Entry entry : optional.entrySet()) { + String fullNodeName = parentNode + "." + entry.getKey(); + + if (dut.nodeExists(fullNodeName)) { + ModelNode node = dut.getNode(fullNodeName); + + Fc actualFc = ((FcModelNode) node).getFc(); + Fc expectedFc = entry.getValue(); + if (!Objects.equals(expectedFc, actualFc)) { + violations.add("Optional node " + fullNodeName + " does not have expected type " + expectedFc + + " but instead " + actualFc); + } + } + else { + // optional node is not present -> nothing more to do + } + } + return violations; + } + + protected static class MandatoryOnCondition { + final String condition; + final String mandatoryOnCondition; + final Fc fc; + + interface SpecifiedCondition { + MandatoryOnCondition thenMandatory(String nodeName, Fc fc); + } + + public static SpecifiedCondition ifPresent(String nodeName) { + return (thenMandatoryNode, fc) -> new MandatoryOnCondition(nodeName, thenMandatoryNode, fc); + } + + private MandatoryOnCondition(String condition, String mandatoryOnCondition, Fc fc) { + this.condition = condition; + this.mandatoryOnCondition = mandatoryOnCondition; + this.fc = fc; + } + } +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java new file mode 100644 index 0000000..4e56b15 --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java @@ -0,0 +1,161 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import de.fhg.ise.testtool.utils.annotations.label.Requirements; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.openmuc.fnn.steuerbox.models.Requirement.LN02a; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN02b; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN02c; +import static org.openmuc.fnn.steuerbox.models.Requirement.S01; +import static org.openmuc.fnn.steuerbox.models.Requirement.S02; +import static org.openmuc.fnn.steuerbox.models.Requirement.S04; +import static org.openmuc.fnn.steuerbox.models.Requirement.S05a; +import static org.openmuc.fnn.steuerbox.models.Requirement.S05b; +import static org.openmuc.fnn.steuerbox.models.Requirement.S05c; +import static org.openmuc.fnn.steuerbox.models.Requirement.S10; +import static org.openmuc.fnn.steuerbox.models.Requirement.S11; +import static org.openmuc.fnn.steuerbox.models.Requirement.S12; + +/** + * Tests suiting the requirements in https://github.com/alliander-opensource/der-scheduling/blob/main/REQUIREMENTS.md + *

+ * Systemoverview available at https://github.com/alliander-opensource/der-scheduling/blob/main/images/system-overview.drawio.png + *

+ * General tests related to 61850 are to be found in {@link ScheduleExecutionTest} + */ +public class AllianderTests extends AllianderBaseTest { + + private static final Logger log = LoggerFactory.getLogger(AllianderTests.class); + + @DisplayName("tenSchedulesAreSupportedPerType") + @Requirements(S01) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void tenSchedulesAreSupportedPerType(ScheduleDefinitions scheduleConstants) { + int j = 0; + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + boolean ScheduleExistsOrNot = dut.nodeExists(scheduleName); + Assertions.assertTrue(ScheduleExistsOrNot, "Schedule " + scheduleName + " does not exist"); + if (ScheduleExistsOrNot) + j++; + } + log.info("There are {} existing schedules at this logical node", j); + } + + @DisplayName("scheduleSupports100values") + @Requirements(S10) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void scheduleSupports100values(ScheduleDefinitions scheduleConstants) { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + assert100ScheduleValuesAreSupported(scheduleConstants, scheduleName); + } + } + + @DisplayName("reserveScheduleSupports100values") + @Requirements(S12) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void reserveScheduleSupports100values(ScheduleDefinitions scheduleConstants) { + assert100ScheduleValuesAreSupported(scheduleConstants, scheduleConstants.getReserveSchedule()); + } + + private void assert100ScheduleValuesAreSupported(ScheduleDefinitions scheduleConstants, String scheduleName) { + final String valNodeName; + if (scheduleConstants.getScheduleType() == ScheduleType.SPG) + valNodeName = ".ValSPG"; + else + valNodeName = ".ValASG"; + for (int i = 1; i <= 100; i++) { + String numberAsStringFilledUpWithZeros = String.format("%03d", i); + String valueConfigurationNode = scheduleName + valNodeName + numberAsStringFilledUpWithZeros; + boolean valueExists = dut.nodeExists(valueConfigurationNode); + Assertions.assertTrue(valueExists, "Missing node " + valueConfigurationNode); + } + } + + @DisplayName("scheduleSupportsTimebasedScheduling") + @Requirements(S02) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void scheduleSupportsTimebasedScheduling(ScheduleDefinitions scheduleConstants) { + for (int i = 1; i <= 10; i++) { + String aTimerNode = scheduleConstants.getScheduleName(i) + ".StrTm01"; + Assertions.assertTrue(dut.nodeExists(aTimerNode), + "Node " + aTimerNode + " does not exist. Time based scheduling is not possible without this node"); + } + } + + @DisplayName("allExpectedSchedulesExist") + @Requirements({ LN02a, LN02b, LN02c }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void allExpectedSchedulesExist(ScheduleDefinitions scheduleConstants) { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + Assertions.assertTrue(dut.nodeExists(scheduleName), + "Expected schedule " + scheduleName + " to exist but did not find it"); + } + } + + @DisplayName("reserveSchedulesExist") + @Requirements(S04) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void reserveSchedulesExist(ScheduleDefinitions scheduleConstants) { + Assertions.assertTrue(dut.nodeExists(scheduleConstants.getReserveSchedule())); + } + + @Requirements(S05a) + @Test + void absolutePowerValueSchedulesAreSupported() { + for (String absolutePowerValueSchedule : dut.powerSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + } + } + + @Requirements(S05b) + @Test + void maxPowerValueSchedulesAreSupported() { + for (String absolutePowerValueSchedule : dut.maxPowerSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + } + } + + @Requirements(S05c) + @Test + void onOffSchedulesAreSupported() { + for (String absolutePowerValueSchedule : dut.onOffSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + } + } + + @Test + @Requirements(S11) + void threeReserveSchedulesExist() { + Assertions.assertTrue(dut.nodeExists(dut.onOffSchedules.getReserveSchedule())); + Assertions.assertTrue(dut.nodeExists(dut.maxPowerSchedules.getReserveSchedule())); + Assertions.assertTrue(dut.nodeExists(dut.powerSchedules.getReserveSchedule())); + } + +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java new file mode 100644 index 0000000..f78b846 --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java @@ -0,0 +1,188 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import com.beanit.iec61850bean.Fc; +import com.beanit.iec61850bean.ServiceError; +import de.fhg.ise.testtool.utils.annotations.label.Requirements; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openmuc.fnn.steuerbox.models.Requirement.E01; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN01; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN02; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN02a; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN02b; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN02c; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN03; + +/** + * Holds tests related to 61850 schedule controller node behaviour + */ +public class ScheduleControllerNodeTests extends AllianderBaseTest { + + /** + * Test if the scheduler has the required nodes with correct types as defined in IEC 61850-90-10:2017, table 6 (page + * 25) + **/ + @DisplayName("checkSubnodes") + @Requirements({ LN03, LN01, LN02 }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void checkSubnodes(ScheduleDefinitions scheduleConstants) { + + // relevant part of the table is the "non-derived-statistics" (nds) column + + Map optional = new HashMap<>(); + Map atMostOne = new HashMap<>(); + Map mandatory = new HashMap<>(); + Map mMulti = new HashMap<>(); + Map oMulti = new HashMap<>(); + + /** + * Descriptions (DC) + */ + optional.put("NamPlt", Fc.DC); + + /** + * Status Information (ST) + */ + mandatory.put("ActSchdRef", Fc.ST); + atMostOne.put("ValINS", Fc.ST); + atMostOne.put("ValSPS", Fc.ST); + atMostOne.put("ValENS", Fc.ST); + mandatory.put("Beh", Fc.ST); + optional.put("Health", Fc.ST); + optional.put("Mir", Fc.ST); + /** + * Measured and metered values (MX) + */ + atMostOne.put("ValMV", Fc.MX); + /** + * Controls + */ + optional.put("Mod", Fc.CO); + /** + * Settings (SP) + */ + mandatory.put("CtlEnt", Fc.SP); + for (int n = 1; n <= 10; n++) { + // n=001..010 is only valid for Alliander tests + String numberAsStringFilledUpWithZeros = String.format("%02d", n); + mMulti.put("Schd" + numberAsStringFilledUpWithZeros, Fc.SP); + } + oMulti.put("InRef", Fc.SP); + + /*** + * Replace this by usages of test + */ + + String controllerNode = scheduleConstants.getController(); + Collection violations = new LinkedList<>(); + violations.addAll(testOptionalNodes(optional, controllerNode)); + violations.addAll(testAtMostOnceNodes(atMostOne, controllerNode)); + violations.addAll(testMandatoryNodes(mandatory, controllerNode)); + violations.addAll(testMMulti(mMulti, controllerNode)); + violations.addAll(testOMulti(oMulti, controllerNode)); + + String delimiter = "\n - "; + String violationsList = delimiter + String.join(delimiter, violations); + + assertTrue(violations.isEmpty(), + "Found violations of node requirements for schedule controller " + controllerNode + ": " + + violationsList + "\n"); + } + + /** + * {@ link Requirements#LN02a} + */ + @DisplayName("activeControllerIsUpdated") + @Requirements({ LN03, LN02a, LN02b, LN02c }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void activeControllerIsUpdated(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + + //initial state: no schedule active -> reserve schedule is working + //test, that ActSchdRef contains a reference of the reserve schedule + + assertEquals(scheduleConstants.getReserveSchedule(), dut.readActiveSchedule(scheduleConstants.getController()), + "Expecting reserve schedules to run in initial state"); + + String schedule = scheduleConstants.getScheduleName(1); + //write and activate a schedule with a higher priority than the reserve schedule + Instant scheduleStart = Instant.now().plus(Duration.ofSeconds(1)); + dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule), + Duration.ofSeconds(2), scheduleStart, 100); + + while (Instant.now().isBefore(scheduleStart.plus(Duration.ofMillis(200)))) { + Thread.sleep(200); + } + + //test, that ActSchdRef contains a reference of the active schedule + assertEquals(schedule, dut.readActiveSchedule(scheduleConstants.getController())); + + // wait until the active schedule finished service + Thread.sleep(2000); + + //make sure the reserve schedule is active again + assertEquals(scheduleConstants.getReserveSchedule(), dut.readActiveSchedule(scheduleConstants.getController()), + "Did not return to system reserve schedule after execution time"); + } + + @DisplayName("activeControllerIsUpdatedWithScheduleOfHighestPrio") + @Requirements({ LN03, E01 }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void activeControllerIsUpdatedWithScheduleOfHighestPrio(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + + // assertEquals(scheduleConstants.getReserveSchedule(), dut.readActiveSchedule(scheduleConstants.getController()), + // "Expecting reserve schedules to run in initial state"); + + Instant start = Instant.now().plus(Duration.ofMillis(500)); + // schedule 1 with low prio + String schedule1Name = scheduleConstants.getScheduleName(1); + dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule1Name), + Duration.ofSeconds(1), start, 20); + + // schedule 2 starts a bit after schedule 1 but with higher prio + String schedule2Name = scheduleConstants.getScheduleName(2); + dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule2Name), + Duration.ofSeconds(1), start.plus(Duration.ofSeconds(1)), 200); + + // wait until start (and a bit longer), then schedule 1 should be active + long millisUntilStart = Duration.between(Instant.now(), start).toMillis(); + Thread.sleep(millisUntilStart + 200); + assertEquals(dut.readActiveSchedule(scheduleConstants.getController()), schedule1Name); + + // sleep 1s, after that schedule 2 should be active + Thread.sleep(1_000); + assertEquals(dut.readActiveSchedule(scheduleConstants.getController()), schedule2Name); + + Thread.sleep(1000); + } +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java new file mode 100644 index 0000000..7c886a8 --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java @@ -0,0 +1,339 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import com.beanit.iec61850bean.ServiceError; +import de.fhg.ise.testtool.utils.annotations.label.Description; +import de.fhg.ise.testtool.utils.annotations.label.Requirements; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; + +import static java.time.Duration.ofMillis; +import static java.time.Duration.ofSeconds; +import static java.time.Instant.now; +import static org.openmuc.fnn.steuerbox.models.Requirement.E01; +import static org.openmuc.fnn.steuerbox.models.Requirement.E02; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN01; +import static org.openmuc.fnn.steuerbox.models.Requirement.S02; +import static org.openmuc.fnn.steuerbox.models.Requirement.S05c; +import static org.openmuc.fnn.steuerbox.models.Requirement.S09; +import static org.openmuc.fnn.steuerbox.models.Requirement.S17; + +/** + * Holds tests related to 61850 schedule execution + */ +public class ScheduleExecutionTest extends AllianderBaseTest { + + private static final Logger log = LoggerFactory.getLogger(ScheduleExecutionTest.class); + + @BeforeAll + public static void setDefaultValuesForReserveSchedules() throws ServiceError, IOException { + dut.writeScheduleValues( + dut.powerSchedules.getValueAccess().prepareWriting(0, dut.powerSchedules.getReserveSchedule())); + dut.writeScheduleValues( + dut.maxPowerSchedules.getValueAccess().prepareWriting(0, dut.maxPowerSchedules.getReserveSchedule())); + dut.writeScheduleValues( + dut.onOffSchedules.getValueAccess().prepareWriting(false, dut.onOffSchedules.getReserveSchedule())); + log.info("Set default values for reserve schedules"); + } + + @DisplayName("test_prioritiesPowerSchedules") + @Requirements({ E02, S02, S05c, E01, LN01, S09 }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getPowerValueSchedules") + public void test_prioritiesPowerSchedules(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException, IEC61850MissconfiguredException { + + // do not change the interval, this is demanded by a requirement! + final Duration interval = ofSeconds(1); + + final Instant testExecutionStart = now(); + final Instant schedulesStart = testExecutionStart.plus(ofSeconds(10)); + + //schedule 1: + dut.writeAndEnableSchedule( + scheduleConstants.prepareSchedule(Arrays.asList(10, 30, 70, 100, 100, 100), 1, interval, + schedulesStart.plus(interval), 25)); + + // schedule 2: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(11, 31, 71, 99, 99, 99), 2, interval, + schedulesStart.plus(interval.multipliedBy(5)), 40)); + + // schedule 3: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(12, 32, 72, 98, 98), 3, interval, + schedulesStart.plus(interval.multipliedBy(9)), 60)); + + //schedule 4, ends after 44s: + dut.writeAndEnableSchedule( + scheduleConstants.prepareSchedule(Arrays.asList(13, 33, 73, 97, 97, 97, 97, 97, 97, 97), 4, interval, + schedulesStart.plus(interval.multipliedBy(13)), 70)); + + //schedule 5, ends after 42s + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70, 70, 70, 70), 5, interval, + schedulesStart.plus(interval.multipliedBy(17)), 100)); + + //schedule 6, + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 6, interval, + schedulesStart.plus(interval.multipliedBy(18)), 120)); + + //schedule 7, + + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 7, interval, + schedulesStart.plus(interval.multipliedBy(20)), 120)); + + //schedule 8: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(10), 8, interval, + schedulesStart.plus(interval.multipliedBy(22)), 80)); + + //schedule 9 + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(80), 9, interval, + schedulesStart.plus(interval.multipliedBy(23)), 20)); + + //schedule 10 + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 10, interval, + schedulesStart.plus(interval.multipliedBy(24)), 11)); + + log.debug("Test setup took {}", Duration.between(testExecutionStart, now())); + + float sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + scheduleConstants.getReserveSchedule()).floatValue(); + + List expectedValues = Arrays.asList(sysResValue, 10f, 30f, 70f, 100f, 11f, 31f, 71f, 99f, 12f, 32f, 72f, + 98f, 13f, 33f, 73f, 97f, 70f, 90f, 70f, 90f, 70f, 10f, 80f, 100f, sysResValue); + + List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(26), + interval, scheduleConstants); + + log.info("expected values {}", expectedValues); + log.info("observed values {}", actualValues); + + assertValuesMatch(expectedValues, actualValues, 0.01); + } + + @DisplayName("test_prioritiesOnOffSchedules") + @Requirements({ E02, S02, S05c, E01 }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getOnOffSchedules") + public void test_prioritiesOnOffSchedules(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, IEC61850MissconfiguredException, InterruptedException { + + // do not change the interval, this is demanded by a requirement! + final Duration interval = ofSeconds(1); + + final Instant testExecutionStart = now(); + final Instant schedulesStart = testExecutionStart.plus(ofSeconds(5)); + + boolean sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + scheduleConstants.getReserveSchedule()); + + log.debug("Test setup took {}", Duration.between(testExecutionStart, now())); + + boolean s1 = false; + boolean s2 = true; + boolean s3 = false; + boolean s4 = true; + boolean s5 = false; + boolean s6 = true; + boolean s7 = false; + boolean s8 = true; + boolean s9 = false; + boolean s10 = true; + + // setting up schedules with increasing priorities, starting one after the other. exception: schedule 10 (is set up last) + + //schedule 1: + dut.writeAndEnableSchedule( + scheduleConstants.prepareSchedule(Arrays.asList(s1, s1, s1), 1, interval, schedulesStart.plus(interval), + 15)); + //schedule 2: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s2, s2, s2), 2, interval, + schedulesStart.plus(interval.multipliedBy(2)), 20)); + //schedule 3: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s3, s3), 3, interval, + schedulesStart.plus(interval.multipliedBy(3)), 30)); + //schedule 4: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s4, s4), 4, interval, + schedulesStart.plus(interval.multipliedBy(4)), 40)); + //schedule 5: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s5, s5), 5, interval, + schedulesStart.plus(interval.multipliedBy(5)), 50)); + //schedule 6: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s6, s6), 6, interval, + schedulesStart.plus(interval.multipliedBy(6)), 60)); + //schedule 7: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s7, s7), 7, interval, + schedulesStart.plus(interval.multipliedBy(7)), 70)); + //schedule 8: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s8, s8), 8, interval, + schedulesStart.plus(interval.multipliedBy(8)), 80)); + //schedule 9: + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s9), 9, interval, + schedulesStart.plus(interval.multipliedBy(9)), 90)); + //schedule 10: starts together with schedule 9 but with lower priority. lasts longer, so is activated after schedule 9 is stopped + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s10, s10), 10, interval, + schedulesStart.plus(interval.multipliedBy(9)), 11)); + + List expectedValues = Arrays.asList(sysResValue, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, sysResValue); + List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(12), + interval, scheduleConstants); + + log.info("expected values {}", expectedValues); + log.info("observed values {}", actualValues); + + assertValuesMatch(expectedValues, actualValues); + } + + /** + * concerning IEC61850 a schedule with the same prio but later start time rules out the one with this prio but + * earlier start time, test for float schedules + */ + @DisplayName("testSamePriosDifferentStartPowerSchedules") + @Description("IEC61850-90-10 ed 2017 Schedule Controller Definitions, section 5.5.3") + @ParameterizedTest(name = " running {0}") + @MethodSource("getPowerValueSchedules") + public void testSamePriosDifferentStartPowerSchedules(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException, IEC61850MissconfiguredException { + + final Instant testExecutionStart = now().plus(ofSeconds(10)); + final Instant schedulesStart = testExecutionStart.plus(ofSeconds(4)); + + //schedule 5, start after 2s, duration 12s, Prio 40 + dut.writeAndEnableSchedule( + scheduleConstants.prepareSchedule(Arrays.asList(10, 10, 10, 10, 10, 10), 5, ofSeconds(4), + schedulesStart, 40)); + //schedule 1, start after 4s, duration 4s, Prio 40 + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 100), 1, ofSeconds(4), + schedulesStart.plus(ofSeconds(4)), 40)); + //schedule 2, start after 8s, duration 4s, Prio 40 + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70), 2, ofSeconds(4), + schedulesStart.plus(ofSeconds(12)), 40)); + //schedule 3, start after 14s, duration 2s, Prio 60 + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 3, ofSeconds(4), + schedulesStart.plus(ofSeconds(24)), 60)); + + float sysResValue = (float) dut.readConstantValueFromSysResScheduleFromModelNode( + scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); + List expectedValues = Arrays.asList(sysResValue, 10f, 70f, 100f, 70f, 70f, 10f, 100f, sysResValue); + + Instant monitoringStart = testExecutionStart.plus(ofSeconds(2)); + List actualValues = dut.monitor(monitoringStart, ofSeconds(36), ofSeconds(4), scheduleConstants); + log.info("expected values {}", expectedValues); + log.info("observed values {}", actualValues); + assertValuesMatch(expectedValues, actualValues, 0.01); + } + + /** + * concerning IEC61850 a schedule with the same prio but later start time rules out the one with this prio but + * earlier start time, test for boolean schedules + */ + @DisplayName("testSamePriosDifferentStartOnOffSchedule") + @Description("IEC61850-90-10 ed 2017 Schedule Controller Definitions, section 5.5.3") + @ParameterizedTest(name = " running {0}") + @MethodSource("getOnOffSchedules") + public void testSamePriosDifferentStartOnOffSchedule(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException, IEC61850MissconfiguredException { + + final Instant testExecutionStart = now(); + final Instant schedulesStart = testExecutionStart.plus(ofSeconds(2)); + + //schedule 1, start after 2s, duration 6s, Prio 40 + dut.writeAndEnableSchedule( + scheduleConstants.prepareSchedule(Arrays.asList(true, true, true), 1, ofSeconds(2), schedulesStart, + 40)); + //schedule 2, start after 4s, duration 4s, Prio 40 + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(false, false), 2, ofSeconds(2), + schedulesStart.plus(ofSeconds(2)), 40)); + + boolean sysResValue = (boolean) dut.readConstantValueFromSysResScheduleFromModelNode( + scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); + List expectedValues = Arrays.asList(sysResValue, true, false, false, sysResValue); + + Instant monitoringStart = testExecutionStart.plus(ofSeconds(1)); + List actualValues = dut.monitor(monitoringStart, ofSeconds(10), ofSeconds(2), scheduleConstants); + log.info("expected values {}", expectedValues); + log.info("observed values {}", actualValues); + assertValuesMatch(expectedValues, actualValues); + } + + /** + * two schedules with the same prio and start: the one with the lower Number in its name rules out the other one, + * e.g. OnOffPow_FSCH04 rules put OnOffPow_FSCH10 IEC61850 does not determine a certain behavior in this case, this + * is just a detail that was fixed for implementation + */ + @DisplayName("test_samePrioAndStartFloatSchedule") + @Requirements({ S17 }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getPowerValueSchedules") + public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, IEC61850MissconfiguredException, InterruptedException { + + float sysResValue = (float) dut.readConstantValueFromSysResScheduleFromModelNode( + scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); + + Instant start = Instant.now(); + PreparedSchedule schedule1 = scheduleConstants.prepareSchedule(Arrays.asList(70f, 70f), 1, ofSeconds(3), + start.plus(ofSeconds(3)), 40); + PreparedSchedule schedule2 = scheduleConstants.prepareSchedule(Arrays.asList(100f, 100f, 100f), 2, ofSeconds(3), + start.plus(ofSeconds(3)), 40); + + dut.writeAndEnableSchedule(schedule1); + dut.writeAndEnableSchedule(schedule2); + + List expectedValues = Arrays.asList(sysResValue, 70f, 70f, 100f, sysResValue); + List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), + scheduleConstants); + assertValuesMatch(expectedValues, actualValues, 0.01); + } + + /** + * two schedules with the same prio and start: the one with the lower Number in its name rules out the other one, + * e.g. OnOffPow_FSCH04 rules put OnOffPow_FSCH10 IEC61850 does not determine a certain behavior in this case, this + * is just a detail that was fixed for implementation + */ + @DisplayName("test_samePrioAndStartOnOffSchedule") + @Requirements({ S17 }) + @ParameterizedTest(name = " running {0}") + @MethodSource("getOnOffSchedules") + public void test_samePrioAndStartOnOffSchedule(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, IEC61850MissconfiguredException, InterruptedException { + boolean sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + scheduleConstants.getReserveSchedule()); + + Instant start = Instant.now(); + PreparedSchedule schedule1 = scheduleConstants.prepareSchedule(Arrays.asList(true, true), 1, ofSeconds(3), + start.plus(ofSeconds(3)), 40); + PreparedSchedule schedule2 = scheduleConstants.prepareSchedule(Arrays.asList(false, false, false), 2, + ofSeconds(3), start.plus(ofSeconds(3)), 40); + + dut.writeAndEnableSchedule(schedule1); + dut.writeAndEnableSchedule(schedule2); + + List expectedValues = Arrays.asList(sysResValue, true, true, false, sysResValue); + List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), + scheduleConstants); + assertValuesMatch(expectedValues, actualValues); + } +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java new file mode 100644 index 0000000..ba49117 --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java @@ -0,0 +1,634 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import com.beanit.iec61850bean.BasicDataAttribute; +import com.beanit.iec61850bean.Fc; +import com.beanit.iec61850bean.FcModelNode; +import com.beanit.iec61850bean.ServiceError; +import de.fhg.ise.testtool.utils.annotations.label.Requirements; +import jdk.jfr.Description; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.function.Executable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleEnablingErrorKind; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleState; +import org.openmuc.fnn.steuerbox.scheduling.ScheduleType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import static java.time.Duration.ofSeconds; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.openmuc.fnn.steuerbox.AllianderBaseTest.MandatoryOnCondition.ifPresent; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN01; +import static org.openmuc.fnn.steuerbox.models.Requirement.LN03; +import static org.openmuc.fnn.steuerbox.models.Requirement.S08; +import static org.openmuc.fnn.steuerbox.models.Requirement.S13; +import static org.openmuc.fnn.steuerbox.models.Requirement.S14; +import static org.openmuc.fnn.steuerbox.models.Requirement.S15; + +/** + * Holds tests related to 61850 schedule node behaviour + */ +public class ScheduleNodeTests extends AllianderBaseTest { + + private static final Logger log = LoggerFactory.getLogger(ScheduleNodeTests.class); + + @DisplayName("hasRequiredSubNodes") + @Requirements(value = { LN03, LN01 }) + @Description("Test if the scheduler has the required nodes with correct types as defined in IEC 61850-90-10:2017, table 7 (page 26)") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void hasRequiredSubNodes(ScheduleDefinitions scheduleConstants) { + + // relevant part of the table is the "non-derived-statistics" (nds) column as there are no derived-statistic + + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + log.info("Testing Schedule {}", scheduleName); + + // Collection of Optional nodes + Map optional = new HashMap<>(); + + // Collection of mandatory nodes that must be present + Map mandatory = new HashMap<>(); + + // Collection of 'AtMostOne' nodes + Map atMostOne = new HashMap<>(); + + //in IEC61850 90-10_2017_end.pdf , table 6, PresConds: MmultiF(), presence under condition + Collection mMultiF = new LinkedList<>(); + + // Collection of Omulti elements (one or several nodes may be present) + Map oMulti = new HashMap<>(); + + /** + * Descriptions (DC) + */ + optional.put("NamPlt", Fc.DC); + + /** + * Status information (ST) + */ + mandatory.put("SchdSt", Fc.ST); + optional.put("SchdEntr", Fc.ST); + atMostOne.put("ValINS", Fc.ST); + atMostOne.put("ValSPS", Fc.ST); + atMostOne.put("ValENS", Fc.ST); + optional.put("ActStrTm", Fc.ST); + mandatory.put("NxtStrTm", Fc.ST); + mandatory.put("SchdEnaErr", Fc.ST); + mandatory.put("Beh", Fc.ST); + optional.put("Health", Fc.ST); + optional.put("Mir", Fc.ST); + mandatory.put("EnaReq", Fc.ST); + mandatory.put("DsaReq", Fc.ST); + + /** + * Measured and metered values (MX) + */ + atMostOne.put("ValMV", Fc.MX); + + /** + * Controls (CO) + */ + optional.put("Mod", Fc.CO); + + /** + * Settings (SP) + */ + optional.put("SchdPrio", Fc.SP); + mandatory.put("NumEntr", Fc.SP); + mandatory.put("SchdIntv", Fc.SP); + //at least one element needs to be present if ValMV is present, otherwise forbidden + mMultiF.add(ifPresent("ValMV").thenMandatory("ValASG001", Fc.SP)); + //at least one element needs to be present if ValINS is present, otherwise forbidden + mMultiF.add(ifPresent("ValINS").thenMandatory("ValING001", Fc.SP)); + //at least one element needs to be present if ValISPS is present, otherwise forbidden + mMultiF.add(ifPresent("ValSPS").thenMandatory("ValSPG001", Fc.SP)); + //at least one element needs to be present if ValENS is present, otherwise forbidden + mMultiF.add(ifPresent("ValENS").thenMandatory("ValENG001", Fc.SP)); + oMulti.put("StrTm", Fc.SP); + optional.put("EvTrg", Fc.SP); + //needs to be present if EvTrg is present, otherwise optional + mMultiF.add(ifPresent("EvTrg").thenMandatory("InSyn", Fc.SP)); + mandatory.put("SchdReuse", Fc.SP); + oMulti.put("InRef", Fc.SP); + + Collection violations = new LinkedList<>(); + violations.addAll(testOptionalNodes(optional, scheduleName)); + violations.addAll(testMandatoryNodes(mandatory, scheduleName)); + violations.addAll(testAtMostOnceNodes(atMostOne, scheduleName)); + violations.addAll(testMMultiF(mMultiF, scheduleName)); + violations.addAll(testOMulti(oMulti, scheduleName)); + + String delimiter = "\n - "; + String violationsList = delimiter + String.join(delimiter, violations); + + assertTrue(violations.isEmpty(), + "Found violations of node requirements for schedule " + scheduleName + ": " + violationsList); + + } + } + + @DisplayName("SchdEntrIsUpdatedWithCurrentlyRunningScheduleIfPresent") + @Requirements(value = LN03) + @Description("Test that SchdEntr is present and is updated by the currently running schedule as described in IEC 61850-90-10:2017, table 7 (page 26)") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void SchdEntrIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + // test if SchdEntr is available + + // test all 10 schedules of one scheduleConstant one by one + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + + //disable the schedule and display the name + dut.disableSchedule(scheduleName); + log.info(scheduleName); + + //check if optional SchEntr is present + boolean isPresent = dut.nodeExists(scheduleName + ".SchdEntr"); + if (isPresent) { + + //display the state of the schedule + log.info("State of the schedule: " + dut.getScheduleState(scheduleName).toString()); + + //if state of the schedule is not RUNNING SchdEntr might be 0 + if (dut.getScheduleState(scheduleName) != ScheduleState.RUNNING) { + String notRunningSchdEntrValueAsString = dut.getNodeEntryasString(scheduleName, "SchdEntr", + "stVal"); + Assertions.assertEquals("0", notRunningSchdEntrValueAsString, + "SchdEntry is not 0 although schedule is not running"); + } + + //now write a schedule and check if SchdEntry is not 0 + PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( + scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), + ofSeconds(8), Instant.now().plusMillis(500), 20); + dut.writeAndEnableSchedule(preparedSchedule); + Thread.sleep(4000); + String runningSchdEntrValueAsString = dut.getNodeEntryasString(scheduleName, "SchdEntr", "stVal"); + Assertions.assertNotEquals("0", runningSchdEntrValueAsString, + "SchdEntry is 0 although schedule is running"); + } + else { + log.info("Optional node SchdEntr not found, skipping test"); + } + } + } + + /** + * INS = Integer status; we do not have integer schedules thus we ValINS should not be present Test that ValINS is + * not present (because it is not relevant for our use case thus we cannot/do not want to test the expected + * behaviour). IEC 61850-90-10:2017, table 7 (page 26) + **/ + @DisplayName("ValINSIsUpdatedWithCurrentlyRunningScheduleIfPresent") + @Requirements(value = LN03) + @Description("Test that ValINS is not available") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void ValINSIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefinitions scheduleConstants) { + testOptionalNodeNotPresent(scheduleConstants, "ValINS"); + } + + /** + * SPS = single point status, we assume that it is the readout value of boolean schedules Test that ValSPS is + * present when having a boolean schedule, in this case it should behave like defined in IEC 61850-90-10:2017, table + * 7 (page 26) if we don't have a boolean schedule we have a float schedule; in this case test that ValMV is present + * and that it behaves like defined in the same table + **/ + @DisplayName("ValSpsOrValMvIsUpdatedWithCurrentlyRunningSchedule") + @Requirements(value = LN03) + @Description("Test ValSPS/ValMv behaves as defined in IEC 61850-90-10:2017, table 7 (page 26) ") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void ValSpsOrValMvIsUpdatedWithCurrentlyRunningSchedule(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + final Duration interval = ofSeconds(1); + final int anyPriorityHigherThanReserveSchedules = 20; + final PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), interval, Instant.now().plusMillis(500), + anyPriorityHigherThanReserveSchedules); + + // initialize: enable schedule, then disable it again + dut.writeAndEnableSchedule(schedule); + Thread.sleep(1500); + dut.disableSchedules(scheduleName); + + final String spsValue = "ValSPS"; + final String mvValue = "ValMV"; + final String shouldExist; + final String shouldNotExist; + final List expectedValues = new LinkedList<>(scheduleConstants.getDefaultValues(1)); + + if (ScheduleType.SPG.equals(scheduleConstants.getScheduleType())) { + shouldExist = spsValue; + shouldNotExist = mvValue; + } + else { + shouldExist = mvValue; + shouldNotExist = spsValue; + } + + assertTrue(dut.nodeExists(scheduleName + "." + shouldExist)); + testOptionalNodeNotPresent(scheduleConstants, shouldNotExist); + Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, shouldExist, "q")); + + final Instant startSecondSchedule = Instant.now().plus(interval).truncatedTo(ChronoUnit.SECONDS); + final Instant startMonitoring = startSecondSchedule.plus(interval.dividedBy(2)); + final PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( + scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), interval, + startSecondSchedule, anyPriorityHigherThanReserveSchedules); + dut.writeAndEnableSchedule(preparedSchedule); + List actualValues = dut.monitor(startMonitoring, interval, interval, scheduleConstants); + + assertUntypedValuesMatch(expectedValues, actualValues); + + log.debug("SUCCESSfully tested {}", scheduleName); + } + } + + /** + * ENS = enumerated status, we do not have a schedule with enumerated value thus we can not have the node ValENS + * Test that ValENS is not present (because it is not relevant for our use case thus we cannot/do not want to test + * the expected behaviour). IEC 61850-90-10:2017, table 7 (page 26) + **/ + @DisplayName("ValEnsIsUpdatedWithCurrentlyRunningScheduleIfPresent") + @Requirements(value = LN03) + @Description("Test that ValENS is not available") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void ValEnsIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefinitions scheduleConstants) { + testOptionalNodeNotPresent(scheduleConstants, "ValENS"); + } + + @DisplayName("ActStrTmIsUpdatedProperly") + @Requirements(value = LN03) + @Description("Test if optional node ActStrTm is present it should behave like defined in IEC 61850-90-10:2017, table 7 (page 26)") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void ActStrTmIsUpdatedProperly(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + if (dut.nodeExists(scheduleName + ".ActStrTm")) { + PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(2), Instant.now().plusMillis(500), + 20); + + //initial status + dut.writeAndEnableSchedule(schedule); + Thread.sleep(1500); + dut.disableSchedules(scheduleName); + + //if schedule is disabled, quality of ActStrTm should be invalid + Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, "ActStrTm", "q")); + + //if schedule is active, ActStrTm.stVal should have the timestamp the active schedule started + Instant timestamp = Instant.now().plusSeconds(2).truncatedTo(ChronoUnit.SECONDS); + PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( + scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), + ofSeconds(4), timestamp, 20); + dut.writeAndEnableSchedule(preparedSchedule); + Thread.sleep(3000); + Assertions.assertEquals(timestamp.toString(), + dut.getNodeEntryasString(scheduleName, "ActStrTm", "stVal")); + } + } + } + + @DisplayName("NxtStrTmIsUpdatedProperly") + @Requirements(value = LN03) + @Description("Test if NxtStrTm is mandatory and should behave like defined in IEC 61850-90-10:2017, table 7 (page 26)") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void NxtStrTmIsUpdatedProperly(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + // disable the schedule such that there is no planned execution + dut.disableSchedules(scheduleName); + + // no planned execution -> NxtStrTm quality should be "INVALID" + Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); + + // create a schedule in future such that we have a planned execution + Instant timestamp = Instant.now().plusSeconds(10).truncatedTo(ChronoUnit.SECONDS); + PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(2), timestamp, 200); + dut.writeAndEnableSchedule(preparedSchedule); + + //if schedule is active, ActStrTm.stVal should have the timestamp the active schedule started and NxtStrTm quality should be "GOOD" + Assertions.assertEquals(timestamp.toString(), dut.getNodeEntryasString(scheduleName, "NxtStrTm", "stVal")); + Assertions.assertEquals("GOOD", dut.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); + } + } + + @DisplayName("EnaReq_operating") + @Requirements(value = LN03) + @Description("Test that EnaReq holds a reasonable error code after provoking errors whilst enabling schedules. " + + "See IEC 61850-90-10:2017, table 7 (page 26)") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void EnaReq_operating(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + + // intial: schedule has valid values set + PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(100), + 100); + dut.writeAndEnableSchedule(preparedSchedule); + dut.disableSchedule(scheduleName); + Thread.sleep(2000); + // test if intial state is correct: should be in inital state + Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + + // test 1: operating with value false should be possible the status should ignore that + BasicDataAttribute enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "false"); + dut.operate((FcModelNode) enableOp.getParent().getParent()); + // still same state: + Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + + // test2: when operating with value true on .EnaReq.Oper.ctlVal and when integrity check passes, schedule should be in ready state + enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dut.operate((FcModelNode) enableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.READY, dut.getScheduleState(scheduleName)); + } + } + + @DisplayName("DsaReq_operating") + @Requirements(value = LN03) + @Description("Test that DsaReq behaves as described in IEC 61850-90-10:2017, table 7 (page 26)") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void DsaReq_operating(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + + // intial: schedule has valid values set + PreparedSchedule initialSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); + dut.writeAndEnableSchedule(initialSchedule); + dut.disableSchedule(scheduleName); + Thread.sleep(2000); + // test if initial state is correct: should be in NOT_READY + Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + + // test if operating with value false on DsaReq is ignored + BasicDataAttribute disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + dut.operate((FcModelNode) disableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + + // test, if in disabled state and operating DsaReq with true, state ist still NOT_READY + disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + dut.operate((FcModelNode) disableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + + // test, if in enabled state and operating DsaReq with true, state turns into NOT_READY + PreparedSchedule updatedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(5), Instant.now().plusSeconds(1), 100); + dut.writeAndEnableSchedule(updatedSchedule); + disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + dut.operate((FcModelNode) disableOp.getParent().getParent()); + Thread.sleep(2000); + Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + } + } + + @DisplayName("schdEnaErr_HoldsMISSING_VALID_NUMENTRcorrectly") + @Requirements(value = { LN03, S08 }) + @Description("Test that SchdEnaErr holds MISSING_VALID_NUMENTR when writing invalid value to NumEntr.setVal (see IEC 61850-90-10:2017, table 7 (page 26))") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void schdEnaErr_HoldsMISSING_VALID_NUMENTRcorrectly(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + + // intial: valid values in NumEntr, Schdintv, SchdValues and test that SchdEnaErr shows no error kind + PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); + dut.writeAndEnableSchedule(schedule); + Thread.sleep(200); + Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dut.getSchdEnaErr(scheduleName)); + dut.disableSchedule(scheduleName); + + // provoke error MISSING_VALID_NUMENTR by setting NumEntr = -1 + dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); + BasicDataAttribute disableOp1 = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, + "false"); + BasicDataAttribute enableOp1 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + // operating will throw, we ignore that error + dut.operate((FcModelNode) disableOp1.getParent().getParent()); + Executable executable1 = () -> { + dut.operate((FcModelNode) enableOp1.getParent().getParent()); + }; + Assertions.assertThrows(ServiceError.class, executable1); + Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_NUMENTR, dut.getSchdEnaErr(scheduleName)); + } + } + + @DisplayName("SchdEnaErrHoldsMISSING_VALID_SCHDINTVcorrectly") + @Requirements(value = { LN03, S08 }) + @Description("Test that SchdEnaErr holds MISSING_VALID_SCHDINTV when writing invalid value to SchdIntv.setVal (see IEC 61850-90-10:2017, table 7 (page 26))") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void SchdEnaErrHoldsMISSING_VALID_SCHDINTVcorrectly(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + + // intial: valid values in NumEntr, Schdintv, SchdValues and test that SchdEnaErr shows no error kind + PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); + dut.writeAndEnableSchedule(schedule); + Thread.sleep(200); + Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dut.getSchdEnaErr(scheduleName)); + dut.disableSchedule(scheduleName); + + // provoke error MISSING_VALID_SCHDINTV by setting SchdIntv = -1 + dut.setDataValues(scheduleName + ".SchdIntv.setVal", null, "-1"); + BasicDataAttribute disableOp1 = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, + "false"); + BasicDataAttribute enableOp1 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + // operating will throw, we ignore that error + dut.operate((FcModelNode) disableOp1.getParent().getParent()); + Executable executable1 = () -> { + dut.operate((FcModelNode) enableOp1.getParent().getParent()); + }; + Assertions.assertThrows(ServiceError.class, executable1); + Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHDINTV, dut.getSchdEnaErr(scheduleName)); + } + } + + /** + * This test exists only for float values, there is no possibility to create such a test for boolean schedules (as + * there are no invalid values for boolean) + */ + @DisplayName("SchdEnaErrHoldsMISSING_VALID_SCHEDULE_VALUEScorrectly") + @Requirements(value = { LN03, S08 }) + @Description("Tests that SchdEnaErr holds the error code MISSING_VALID_SCHEDULE_VALUE when invalid values are written, for (Max)Power Schedules (see IEC 61850-90-10:2017, table 7 (page 26))") + @ParameterizedTest(name = " running {0}") + @MethodSource("getPowerValueSchedules") + void SchdEnaErrHoldsMISSING_VALID_SCHEDULE_VALUEScorrectly(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + for (String scheduleName : scheduleConstants.getAllScheduleNames()) { + + // intial: valid values in SchdValues, test that it shows no error kind + int scheduleNumber = scheduleConstants.getScheduleNumber(scheduleName); + PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleNumber, ofSeconds(1), Instant.now().plusSeconds(2), 100); + dut.writeAndEnableSchedule(schedule); + Thread.sleep(200); + Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dut.getSchdEnaErr(scheduleName)); + dut.disableSchedule(scheduleName); + + //Provoke MISSING_VALID_SCHEDULE_VALUES error kind by writing invalid values + Executable excecutable = () -> { + dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule( + Arrays.asList(Float.NaN, Float.MAX_VALUE, Float.POSITIVE_INFINITY), scheduleNumber, + ofSeconds(2), Instant.now().plusSeconds(1), 100)); + }; + Assertions.assertThrows(ServiceError.class, excecutable); + Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHEDULE_VALUES, + dut.getSchdEnaErr(scheduleName)); + } + } + + @DisplayName("NumEntr_range") + @Requirements(value = LN03) + @Description( + "Test that NumEntr can only be set to values > 0 and values <= the number of instantiated Val[ASG|ING|SPG|ENG]'s " + + "as stated in IEC 61850-90-10:2017, table 7 (page 26)") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + void NumEntr_range(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException, InterruptedException { + + String scheduleName = scheduleConstants.getScheduleName(1); + // intial: valid values in NumEntr + PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), + scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); + dut.writeAndEnableSchedule(schedule); + Thread.sleep(200); + dut.disableSchedule(scheduleName); + + //test: 0 can not bet set to NumEtr + dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "0"); + BasicDataAttribute disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dut.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable = () -> dut.operate((FcModelNode) enableOp.getParent().getParent()); + Assertions.assertThrows(ServiceError.class, executable); + + //test: -1 can not bet set to NumEtr + dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); + disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp2 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dut.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable2 = () -> dut.operate((FcModelNode) enableOp2.getParent().getParent()); + Assertions.assertThrows(ServiceError.class, executable2); + + //test: 200 can not bet set to NumEtr + dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "200"); + disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp3 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dut.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable3 = () -> dut.operate((FcModelNode) enableOp3.getParent().getParent()); + Assertions.assertThrows(ServiceError.class, executable3); + + } + + @DisplayName("reserveSchedulesCannotBeDeactivated") + @Requirements(S13) + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + public void reserveSchedulesCannotBeDeactivated(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException { + + disableAllRunningSchedules(); + log.debug("Disabled all running schedules"); + + // if all other schedules are deactivated, the reserve schedule should be running + final String reserveSchedule = scheduleConstants.getReserveSchedule(); + Assertions.assertEquals(ScheduleState.RUNNING, dut.getScheduleState(reserveSchedule)); + try { + dut.disableSchedules(reserveSchedule); + } catch (ServiceError e) { + // an access violation may be thrown here, this indicates the schedule cannot be deactivated + } + Assertions.assertEquals(ScheduleState.RUNNING, dut.getScheduleState(reserveSchedule)); + } + + @DisplayName("reserveSchedulesHaveFixedPriority") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + @Requirements(S14) + public void reserveSchedulesHaveFixedPriority(ScheduleDefinitions scheduleConstants) + throws ServiceError, IOException { + final String reserveSchedule = scheduleConstants.getReserveSchedule(); + try { + dut.setSchedulePrio(reserveSchedule, 100); + } catch (ServiceError e) { + // an access violation may be thrown here, this indicates the prio cannot be changed + } + Assertions.assertEquals(10, dut.readSchedulePrio(reserveSchedule)); + } + + @DisplayName("reserveSchedulesHaveFixedStart") + @ParameterizedTest(name = " running {0}") + @MethodSource("getAllSchedules") + @Requirements(S15) + public void reserveSchedulesHaveFixedStart(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException { + final String reserveSchedule = scheduleConstants.getReserveSchedule(); + Assertions.assertEquals(Instant.ofEpochSecond(1), dut.getScheduleStart(reserveSchedule)); + try { + dut.setScheduleStart(reserveSchedule, Instant.now()); + } catch (ServiceError e) { + // an access violation may be thrown here, this indicates the start date cannot be changed + } + Assertions.assertEquals(Instant.ofEpochSecond(1), dut.getScheduleStart(reserveSchedule)); + } + + /** + * ############################### UTILITIES AND HELPERS ################################## + */ + + /** + * Tests that a node is not present in the model. This is to facilitate testing as we can simply leave out nodes + * that are not relevant for our use case. + */ + private void testOptionalNodeNotPresent(ScheduleDefinitions scheduleConstants, String nodeName) { + scheduleConstants.getAllScheduleNames().forEach(schedule -> { + org.junit.jupiter.api.Assertions.assertFalse(dut.nodeExists(schedule + "." + nodeName), + "Optional node " + nodeName + + " not relevant for this use case, so it should be left out (behavior cannot be tested)."); + }); + } +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java new file mode 100644 index 0000000..4c230d9 --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2023 Fraunhofer ISE + * + * 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 + * + * https://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. + */ + +package org.openmuc.fnn.steuerbox; + +import com.beanit.iec61850bean.ServiceError; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; +import org.openmuc.fnn.steuerbox.models.AllianderDER; + +import java.io.IOException; + +import static org.openmuc.fnn.steuerbox.AllianderTests.extractNumberFromLastNodeName; + +public class UtilityTest { + + @Test + void numberExtractionWorks() { + Assertions.assertEquals( + extractNumberFromLastNodeName("device4.schedule76.whatever.in.between.number123").get().intValue(), + 123); + } + + @Test + void numberExtractionDoesNotThrow() { + Assertions.assertTrue(extractNumberFromLastNodeName("").isEmpty()); + Assertions.assertTrue(extractNumberFromLastNodeName("nonumberinhere").isEmpty()); + } + + @Test + public void testReserveScheduleWorksAsExpected() throws ServiceError, IOException, IEC61850MissconfiguredException { + float expectedValue = 123f; + + AllianderDER dut = AllianderDER.getWithDefaultSettings(); + String reserveScheduleName = dut.powerSchedules.getReserveSchedule(); + // set number of values to 1 + dut.setDataValues(reserveScheduleName + ".NumEntr.setVal", null, "1"); + // write expected values + String valueBasicDataAttribute = String.format("%s.ValASG001.setMag.f", reserveScheduleName); + dut.setDataValues(valueBasicDataAttribute, null, Float.toString(expectedValue)); + + Assertions.assertEquals(expectedValue, + (float) dut.readConstantValueFromSysResScheduleFromModelNode(dut.powerSchedules.getValueAccess(), + reserveScheduleName)); + } + + @Test + void test_ReadingReserveScheduleFails_When2ComposedFromMoreThan1Element() throws ServiceError, IOException { + + float firstValue = 10f; + float secondValue = 20f; + + AllianderDER dut = AllianderDER.getWithDefaultSettings(); + String reserveScheduleName = dut.powerSchedules.getReserveSchedule(); + + //write two values in reserveSchedule + String valueBasicDataAttribute1 = String.format("%s.ValASG001.setMag.f", reserveScheduleName); + String valueBasicDataAttribute2 = String.format("%s.ValASG002.setMag.f", reserveScheduleName); + + dut.setDataValues(valueBasicDataAttribute1, null, Float.toString(firstValue)); + dut.setDataValues(valueBasicDataAttribute2, null, Float.toString(secondValue)); + // set number of values (NumEntr) to 2 + dut.setDataValues(reserveScheduleName + ".NumEntr.setVal", null, "2"); + + Executable executableThatShouldThrow = () -> dut.readConstantValueFromSysResScheduleFromModelNode( + dut.powerSchedules.getValueAccess(), reserveScheduleName); + IEC61850MissconfiguredException caughtException = Assertions.assertThrows(IEC61850MissconfiguredException.class, + executableThatShouldThrow); + Assertions.assertEquals( + "Expected exactly 1 power value in system reserve Schedule but got 2. Please reconfigure the device.", + caughtException.getMessage()); + + } + + @Test + void removeingNumbersWorks() { + Assertions.assertEquals("asd", AllianderBaseTest.removeNumbers("asd123")); + Assertions.assertEquals(null, AllianderBaseTest.removeNumbers(null)); + Assertions.assertEquals("", AllianderBaseTest.removeNumbers("42")); + Assertions.assertEquals("no number", AllianderBaseTest.removeNumbers("no number")); + } +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java new file mode 100644 index 0000000..96d4735 --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java @@ -0,0 +1,25 @@ +package org.openmuc.fnn.steuerbox; + +import de.fhg.ise.testtool.utils.annotations.label.Description; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Path; + +public class VersionTest { + + public final static String EXPECTED_LIB_IEC_61850_VERSION = "1.5.2"; + + @Description("Checks installed library version of libiec61850. Expects v" + EXPECTED_LIB_IEC_61850_VERSION + ".") + @DisplayName("IEC 61850 Protocol Library version check") + @Test + void libIecVersionMatchesExpectedVersion() throws IOException { + final String libIecLink = "/usr/local/lib/libiec61850.so"; + Path path = Path.of(libIecLink).toRealPath(); + String versionSuffix = path.toString().replaceAll(libIecLink + ".", ""); + + Assertions.assertEquals(EXPECTED_LIB_IEC_61850_VERSION, versionSuffix); + } +} diff --git a/conformance-tests/src/test/resources/logback-test.xml b/conformance-tests/src/test/resources/logback-test.xml new file mode 100644 index 0000000..7f61ef2 --- /dev/null +++ b/conformance-tests/src/test/resources/logback-test.xml @@ -0,0 +1,31 @@ + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + ${application.home:-.}/testResults/${timestamp}-schedule-test.log + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + \ No newline at end of file From 38c81ad99b58063abd7727704b5a64ec6b062646 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 19 Jun 2024 14:58:04 +0200 Subject: [PATCH 04/15] Update dependencies Signed-off-by: Daniel Werner --- conformance-tests/allowed-licenses.json | 8 +- conformance-tests/build.gradle | 103 +++++++++--------- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/conformance-tests/allowed-licenses.json b/conformance-tests/allowed-licenses.json index d6a1abb..8dc193d 100644 --- a/conformance-tests/allowed-licenses.json +++ b/conformance-tests/allowed-licenses.json @@ -12,23 +12,23 @@ }, { "moduleLicense": "Apache License, Version 2.0", - "moduleVersion": "2.11.0", + "moduleVersion": "2.16.1", "moduleName": "commons-io:commons-io" }, { "comment": "MIT can be included into Apache 2.0 according https://www.apache.org/legal/resolved.html#category-a (31.1.23)", "moduleLicense": "MIT License", - "moduleVersion": "2.0.4", + "moduleVersion": "2.0.13", "moduleName": "org.slf4j:slf4j-api" }, { "comment": "uses dual license, we use Eclipse Public License - v 1.0 which can be included into Apache 2.0 according to https://www.apache.org/legal/resolved.html#category-b (31.1.23)", - "moduleVersion": "1.4.5", + "moduleVersion": "1.5.6", "moduleName": "ch.qos.logback:logback-core" }, { "comment": "uses dual license, we use Eclipse Public License - v 1.0 which can be included into Apache 2.0 according to https://www.apache.org/legal/resolved.html#category-b (31.1.23)", - "moduleVersion": "1.4.5", + "moduleVersion": "1.5.6", "moduleName": "ch.qos.logback:logback-classic" } ] diff --git a/conformance-tests/build.gradle b/conformance-tests/build.gradle index ae33596..46decd9 100755 --- a/conformance-tests/build.gradle +++ b/conformance-tests/build.gradle @@ -1,51 +1,52 @@ -//############################################################################# -//Global configuration -//############################################################################# - - -plugins { - id 'java-library' - id 'com.github.jk1.dependency-license-report' version '2.0' -} -repositories { - mavenCentral() -} -dependencies { - implementation 'ch.qos.logback:logback-classic:1.4.5' - implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.4' - - implementation group: 'com.beanit', name: 'iec61850bean', version: '1.9.0' - implementation group: 'commons-io', name: 'commons-io', version: '2.11.0' - - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' - testImplementation 'org.junit.jupiter:junit-jupiter-params:5.3.1' - -} - -jar { - manifest { - attributes( - 'Main-Class': 'org.openmuc.fnn.steuerbox.ScheduleWriterExample' - ) - } - from { - configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } - } -} - -test { - useJUnitPlatform() -} - - -import com.github.jk1.license.render.XmlReportRenderer - -licenseReport { - outputDir = "$projectDir/build/licenses" - configurations = ['runtimeClasspath'] - excludeOwnGroup = true - excludeBoms = false - renderers = [new XmlReportRenderer('third-party-libs.xml', 'Back-End Libraries')] - allowedLicensesFile = new File("$projectDir/allowed-licenses.json") -} \ No newline at end of file +//############################################################################# +//Global configuration +//############################################################################# + + +plugins { + id 'java-library' + id 'com.github.jk1.dependency-license-report' version '2.8' +} +repositories { + mavenCentral() +} +dependencies { + implementation 'ch.qos.logback:logback-classic:1.5.6' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.13' + + implementation group: 'com.beanit', name: 'iec61850bean', version: '1.9.0' + implementation group: 'commons-io', name: 'commons-io', version: '2.16.1' + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.2' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.2' + +} + +jar { + manifest { + attributes( + 'Main-Class': 'org.openmuc.fnn.steuerbox.ScheduleWriterExample' + ) + } + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } +} + +test { + useJUnitPlatform() +} + + +import com.github.jk1.license.render.XmlReportRenderer + +licenseReport { + outputDir = "$projectDir/build/licenses" + configurations = ['runtimeClasspath'] + excludeOwnGroup = true + excludeBoms = false + renderers = [new XmlReportRenderer('third-party-libs.xml', 'Back-End Libraries')] + allowedLicensesFile = new File("$projectDir/allowed-licenses.json") +} + diff --git a/conformance-tests/gradle/wrapper/gradle-wrapper.properties b/conformance-tests/gradle/wrapper/gradle-wrapper.properties index f371643..3994438 100644 --- a/conformance-tests/gradle/wrapper/gradle-wrapper.properties +++ b/conformance-tests/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 972ff2c9afbf212bfd4746706ac2517ecb1cf708 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 19 Jun 2024 15:10:16 +0200 Subject: [PATCH 05/15] Implement new tests Signed-off-by: Daniel Werner --- conformance-tests/.gitignore | 7 + conformance-tests/allowed-licenses.json | 23 +- conformance-tests/build.gradle | 3 + conformance-tests/checkLicense.sh | 1 - .../conformance-tests/.gitignore | 2 - conformance-tests/run-all-tests.sh | 9 + conformance-tests/run-demo-tests.sh | 3 - .../org/openmuc/fnn/steuerbox/Context.java | 8 + .../fnn/steuerbox/ScheduleWriterExample.java | 111 ------- .../fnn/steuerbox/models/AllianderDER.java | 2 +- .../openmuc/fnn/steuerbox/mqtt/Command.java | 60 ++++ .../fnn/steuerbox/mqtt/ParsingUtil.java | 71 +++++ .../openmuc/fnn/steuerbox/mqtt/Schedule.java | 89 ++++++ .../steuerbox/mqtt/ScheduleResolution.java | 34 +++ .../scheduling/PreparedSchedule.java | 15 +- .../scheduling/ScheduleDefinitions.java | 5 +- .../steuerbox/scheduling/ScheduleType.java | 2 +- .../fnn/steuerbox/scheduling/ValueAccess.java | 31 +- .../{ => testutils}/IEC61850Utility.java | 78 ++--- .../fnn/steuerbox/testutils/MqttUtility.java | 189 ++++++++++++ .../steuerbox/testutils/ScheduleWriter.java | 22 ++ .../fnn/steuerbox/AllianderBaseTest.java | 34 ++- .../fnn/steuerbox/EmsInterfacingTests.java | 289 ++++++++++++++++++ .../ScheduleControllerNodeTests.java | 2 + .../fnn/steuerbox/ScheduleExecutionTest.java | 10 +- .../openmuc/fnn/steuerbox/UtilityTest.java | 50 ++- .../openmuc/fnn/steuerbox/VersionTest.java | 20 ++ 27 files changed, 941 insertions(+), 229 deletions(-) create mode 100644 conformance-tests/.gitignore delete mode 100644 conformance-tests/conformance-tests/.gitignore delete mode 100755 conformance-tests/run-demo-tests.sh delete mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Command.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ParsingUtil.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Schedule.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ScheduleResolution.java rename conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/{ => testutils}/IEC61850Utility.java (88%) create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java create mode 100644 conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/ScheduleWriter.java create mode 100644 conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java diff --git a/conformance-tests/.gitignore b/conformance-tests/.gitignore new file mode 100644 index 0000000..ca7ef8c --- /dev/null +++ b/conformance-tests/.gitignore @@ -0,0 +1,7 @@ +testResults/ +build +.gradle/ +.idea/ +allure-results/ +.venv/ +testtool-out/ diff --git a/conformance-tests/allowed-licenses.json b/conformance-tests/allowed-licenses.json index 8dc193d..9f9b8d8 100644 --- a/conformance-tests/allowed-licenses.json +++ b/conformance-tests/allowed-licenses.json @@ -1,19 +1,16 @@ { "allowedLicenses": [ { - "moduleLicense": "The Apache License, Version 2.0", - "moduleVersion": "1.12.0", - "moduleName": "com.beanit:asn1bean" + "moduleLicense": "The Apache License, Version 2.0" }, { - "moduleLicense": "The Apache License, Version 2.0", - "moduleVersion": "1.9.0", - "moduleName": "com.beanit:iec61850bean" + "moduleLicense": "Apache License, Version 2.0" }, { - "moduleLicense": "Apache License, Version 2.0", - "moduleVersion": "2.16.1", - "moduleName": "commons-io:commons-io" + "moduleLicense": "Apache 2.0" + }, + { + "moduleLicense": "The Apache Software License, Version 2.0" }, { "comment": "MIT can be included into Apache 2.0 according https://www.apache.org/legal/resolved.html#category-a (31.1.23)", @@ -30,6 +27,12 @@ "comment": "uses dual license, we use Eclipse Public License - v 1.0 which can be included into Apache 2.0 according to https://www.apache.org/legal/resolved.html#category-b (31.1.23)", "moduleVersion": "1.5.6", "moduleName": "ch.qos.logback:logback-classic" + }, + { + "comment": "MIT can be included into Apache 2.0 according https://www.apache.org/legal/resolved.html#category-a (03.06.2024)", + "moduleLicense": "MIT-0", + "moduleVersion": "1.0.4", + "moduleName": "org.reactivestreams:reactive-streams" } ] -} \ No newline at end of file +} diff --git a/conformance-tests/build.gradle b/conformance-tests/build.gradle index 46decd9..d0b8206 100755 --- a/conformance-tests/build.gradle +++ b/conformance-tests/build.gradle @@ -14,6 +14,8 @@ dependencies { implementation 'ch.qos.logback:logback-classic:1.5.6' implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.13' + implementation("com.fasterxml.jackson.core:jackson-databind:2.17.1") + implementation group: 'com.beanit', name: 'iec61850bean', version: '1.9.0' implementation group: 'commons-io', name: 'commons-io', version: '2.16.1' @@ -21,6 +23,7 @@ dependencies { testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.2' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.2' + implementation("com.hivemq:hivemq-mqtt-client:1.3.3") } jar { diff --git a/conformance-tests/checkLicense.sh b/conformance-tests/checkLicense.sh index ad5cee3..2ab1411 100755 --- a/conformance-tests/checkLicense.sh +++ b/conformance-tests/checkLicense.sh @@ -1,5 +1,4 @@ #!/bin/bash - # Skript to check proper licensing setup ./gradlew clean checkLicense diff --git a/conformance-tests/conformance-tests/.gitignore b/conformance-tests/conformance-tests/.gitignore deleted file mode 100644 index ce62f63..0000000 --- a/conformance-tests/conformance-tests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.gradle/ -.idea/ diff --git a/conformance-tests/run-all-tests.sh b/conformance-tests/run-all-tests.sh index 1d19c1d..aa85a95 100755 --- a/conformance-tests/run-all-tests.sh +++ b/conformance-tests/run-all-tests.sh @@ -1,3 +1,12 @@ #!/bin/bash + +./gradlew checkLicense + +echo TODO: start the below as screen sessions, stop after tests! +echo "cd ../deployments/n61850-smqtt-ubuntu2004/ && docker-compose up" +echo "cd ../hedera-61850-gateway/ && docker-compose up" +echo mosquitto_sub -t fledge/south-schedule -i schedule-subscriber +echo mosquitto_sub -t fledge/south-command -i cmd-subscriber + ./gradlew test echo "All tests run. Please see the logs in testResults/ directory for details" diff --git a/conformance-tests/run-demo-tests.sh b/conformance-tests/run-demo-tests.sh deleted file mode 100755 index 18b852b..0000000 --- a/conformance-tests/run-demo-tests.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -./gradlew test --tests *ScheduleExecutionTest.test_priorities -echo "Demo tests run. Please see the logs in testResults/ directory for details" diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java index 0397017..056f631 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/Context.java @@ -13,6 +13,8 @@ package org.openmuc.fnn.steuerbox; +import com.fasterxml.jackson.databind.ObjectMapper; + import javax.xml.parsers.DocumentBuilderFactory; /** @@ -22,7 +24,13 @@ public class Context { private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + private static final ObjectMapper objectMapper = new ObjectMapper(); + public static DocumentBuilderFactory getDocumentBuilderFactory() { return factory; } + + public static ObjectMapper getObjectMapper() { + return objectMapper; + } } diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java deleted file mode 100644 index 025c19b..0000000 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/ScheduleWriterExample.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2023 Fraunhofer ISE - * - * 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 - * - * https://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. - */ - -package org.openmuc.fnn.steuerbox; - -import org.openmuc.fnn.steuerbox.models.AllianderDER; -import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.time.Duration; -import java.time.Instant; -import java.util.Arrays; -import java.util.List; - -import static java.lang.Integer.parseInt; -import static java.time.Duration.ofSeconds; -import static java.time.Instant.now; -import static java.util.stream.Collectors.toList; - -/** - * Example class to show how modifying schedules works. Not actually relevant for testing, rather intended as an example - * on how to modify schedules. - */ -public class ScheduleWriterExample { - - public static final String HOST_NAME = "192.168.17.200"; - - private static Logger log = LoggerFactory.getLogger(ScheduleWriterExample.class); - - public static void main(String[] args) { - final Instant setupStart = now(); - final List argList = Arrays.asList(args); - try { - final Duration interval = ofSeconds(5); - log.info("Got args {}", argList); - - if (argList.size() < 4) { - throw new IllegalArgumentException("Too few arguments"); - } - - final int schedule_number = parseInt(argList.get(0)); - final int seconds = parseInt(argList.get(1)); - final Instant start = now().plusSeconds(seconds); - final int prio = parseInt(argList.get(2)); - final List values = argList.stream()// - .skip(3)// - .map(Integer::parseInt)// - .collect(toList()); - - if (seconds < 1) { - throw new IllegalArgumentException("Seconds " + seconds + " needs to be at last 1"); - } - - if (schedule_number < 1 || schedule_number > 10) { - throw new IllegalArgumentException( - "Illegal schedule number " + schedule_number + " needs to be between 1 and 10"); - } - - if (prio < 10) { - throw new IllegalArgumentException("Prio " + prio + "too low: needs to be equal to or larger than 10"); - } - - log.info("Setting up new schedule with prio {} starting at {} with interval {} and values {}", prio, start, - interval, values); - - try (final AllianderDER allianderDER = new AllianderDER(HOST_NAME, 102)) { - PreparedSchedule preparedSchedule = allianderDER.maxPowerSchedules.prepareSchedule(values, - schedule_number, interval, start, prio); - allianderDER.writeAndEnableSchedule(preparedSchedule); - - } catch (Exception e) { - throw new ScheduleEnableException(e); - } - log.info("SUCCESS! Set up schedule in {}", Duration.between(setupStart, Instant.now())); - log.info("Schedule will start running in {} (IN CASE THE CLOCK OF THE DEVICE IS SET UP PROPERLY)", - Duration.between(now(), start)); - } catch (ScheduleEnableException e) { - log.error("Execution occured while setting up schedule", e.cause); - log.error("Unable to activate schedule, exiting"); - System.exit(1); - } catch (Exception e) { - String explantion = "(schedule number [1-10]) (seconds until start > 1) (prio > 10) (value1 value2 value3)"; - String example = "1 30 42 0 10 20 30 40"; - log.error("Unable to parse input args '{}', failed with {}: {}", argList, e.getClass(), e.getMessage()); - log.info("Arguments '{}' could not be parsed (see above).", argList); - log.info("Expecting something like '{}'", example); - log.info("or at least like '{}'", "1 0 11 42"); - log.info("where '{}'.", explantion); - System.exit(2); - } - } - - static class ScheduleEnableException extends Exception { - final Exception cause; - - public ScheduleEnableException(Exception cause) { - this.cause = cause; - } - } -} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java index 46ed17b..520e680 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/models/AllianderDER.java @@ -14,9 +14,9 @@ package org.openmuc.fnn.steuerbox.models; import com.beanit.iec61850bean.ServiceError; -import org.openmuc.fnn.steuerbox.IEC61850Utility; import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; import org.openmuc.fnn.steuerbox.scheduling.ScheduleType; +import org.openmuc.fnn.steuerbox.testutils.IEC61850Utility; import java.io.IOException; diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Command.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Command.java new file mode 100644 index 0000000..e33febe --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Command.java @@ -0,0 +1,60 @@ +package org.openmuc.fnn.steuerbox.mqtt; + +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static org.openmuc.fnn.steuerbox.mqtt.ParsingUtil.parseMqttMessages; + +/** + * A command payload representing a control signal intended for the EMS. + *

+ * Only relevant parameters will be parsed, most of the JSON fields are FLEDGE defaults and not relevant for the + * ReLevENT use cases. + */ +public class Command { + public Command(long epochSecond, double controlValue) { + this.epochSecond = epochSecond; + this.controlValue = controlValue; + } + + public final long epochSecond; + public final double controlValue; + + public static Command fromJsonString(String command) + throws ParserConfigurationException, IOException, SAXException { + List> entries = parseMqttMessages(command); + if (entries.size() != 1) { + throw new IllegalArgumentException( + "Expected exactly 1 element to be returned. Are you trying to parse a schedule as a command?"); + } + Map.Entry instantDoubleEntry = entries.get(0); + return new Command(instantDoubleEntry.getKey().getEpochSecond(), instantDoubleEntry.getValue()); + } + + @Override + public String toString() { + return "Command{" + "epochSecond=" + epochSecond + "(equivalent to " + Instant.ofEpochSecond(epochSecond) + + "), controlValue=" + controlValue + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Command command = (Command) o; + return epochSecond == command.epochSecond && Double.compare(controlValue, command.controlValue) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(epochSecond, controlValue); + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ParsingUtil.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ParsingUtil.java new file mode 100644 index 0000000..66cb63e --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ParsingUtil.java @@ -0,0 +1,71 @@ +package org.openmuc.fnn.steuerbox.mqtt; + +import com.fasterxml.jackson.databind.JsonNode; +import org.openmuc.fnn.steuerbox.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Duration; +import java.time.Instant; +import java.util.AbstractMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Utilities to parse JSON messages + */ +public class ParsingUtil { + + private final static Logger log = LoggerFactory.getLogger(ParsingUtil.class); + + private ParsingUtil() { + // prevent calling constructor: utility class with no members + } + + /** + * Deserialize a schedule for communication with HEDERA-61850-interface. + *

+ * Will use a switch to not communicate the request to HEDERA but instead immediately forward it to the IEC 61850 + * FLEDGE scheduling server + */ + public static String scheduleToJson(List values, Duration interval, Instant start) { + ScheduleResolution scheduleResolution = ScheduleResolution.from(interval); + return String.format("{\"skipHedera\":true," // + + "\"direction\":\"IMPORT\","// + + "\"start\":{\"seconds\":%s,\"nanos\":%s},"// + + "\"resolution\":\"%s\"," // + + "\"values\":[%s]}", start.getEpochSecond(), start.getNano(), scheduleResolution.name(), + values.stream().map(Object::toString).collect(Collectors.joining(","))); + } + + /** + * Utility to parse command or schedule parameters from a JSON message (command and schedules are very alike: a + * schedule is like an array of commands) + */ + static List> parseMqttMessages(String commandOrScheduleJson) { + List> entities = new LinkedList<>(); + try { + Iterator parameters = Context.getObjectMapper() + .readTree(commandOrScheduleJson) + .get("parameters") + .elements(); + while (parameters.hasNext()) { + JsonNode parameter = parameters.next(); + JsonNode apcTypNode = parameter.get("value").get("GTIC").get("ApcTyp"); + JsonNode tNode = apcTypNode.get("t"); + long epochSeconds = tNode.get("SecondSinceEpoch").longValue(); + double controlValue = apcTypNode.get("ctlVal").asDouble(); + long nanos = 0; // could be created from FractionOfSecond, but testing does not make sense on that base.. + log.trace("Ignoring FractionOfSecond, testing on that base does not make sense"); + entities.add(new AbstractMap.SimpleEntry<>(Instant.ofEpochSecond(epochSeconds, nanos), controlValue)); + } + return entities; + } catch (Exception e) { + throw new RuntimeException( + "Unable deserialize command from '" + commandOrScheduleJson + "': Required elements not found.", e); + } + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Schedule.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Schedule.java new file mode 100644 index 0000000..29d0008 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/Schedule.java @@ -0,0 +1,89 @@ +package org.openmuc.fnn.steuerbox.mqtt; + +import java.time.Instant; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static org.openmuc.fnn.steuerbox.mqtt.ParsingUtil.parseMqttMessages; + +/** + * A command payload representing a result schedule intended for the EMS to facilitate optimization of the energy + * system. + *

+ * Only relevant parameters will be parsed, most of the JSON fields are FLEDGE defaults and not relevant for the + * ReLevENT use cases. + */ +public class Schedule { + private List scheduleEntries = new LinkedList<>(); + + public Schedule(ScheduleEntry... entries) { + for (ScheduleEntry entry : entries) { + this.scheduleEntries.add(entry); + } + } + + public List getScheduleEntries() { + return Collections.unmodifiableList(this.scheduleEntries); + } + + public static Schedule parse(String scheduleString) { + List> entries = parseMqttMessages(scheduleString); + Schedule schedule = new Schedule(); + entries.forEach( + e -> schedule.scheduleEntries.add(new ScheduleEntry(e.getKey().getEpochSecond(), e.getValue()))); + return schedule; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Schedule schedule = (Schedule) o; + return Objects.equals(scheduleEntries, schedule.scheduleEntries); + } + + @Override + public int hashCode() { + return Objects.hashCode(scheduleEntries); + } + + public static class ScheduleEntry { + public final long startEpochSecond; + public final double controlValue; + + public ScheduleEntry(long startEpochSecond, double controlValue) { + this.startEpochSecond = startEpochSecond; + this.controlValue = controlValue; + } + + @Override + public String toString() { + return "ScheduleEntry{" + "startEpochSecond=" + startEpochSecond + ", controlValue=" + controlValue + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + ScheduleEntry that = (ScheduleEntry) o; + return startEpochSecond == that.startEpochSecond && Double.compare(controlValue, that.controlValue) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(startEpochSecond, controlValue); + } + } + + @Override + public String toString() { + return "Schedule{" + "scheduleEntries=" + scheduleEntries + '}'; + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ScheduleResolution.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ScheduleResolution.java new file mode 100644 index 0000000..5ee059d --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/mqtt/ScheduleResolution.java @@ -0,0 +1,34 @@ +package org.openmuc.fnn.steuerbox.mqtt; + +import java.time.Duration; +import java.util.Arrays; +import java.util.stream.Collectors; + +/** + * Schedule resolutions as supported by HEDERA API. + *

+ * At the state of implementation, this only covered only 5 minute and 15 minute resolutions. + */ +public enum ScheduleResolution { + FIVE_MINUTES(Duration.ofMinutes(5)), + FIFTEEN_MINUTES(Duration.ofMinutes(15)); + + private final Duration duration; + + ScheduleResolution(Duration duration) { + this.duration = duration; + } + + static ScheduleResolution from(Duration duration) { + return Arrays.stream(ScheduleResolution.values()) + .filter(rs -> rs.duration.equals(duration)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException( + "Unable to map " + duration + " to a schedule resolution. Valid values are: " + Arrays.stream( + values()).map(ScheduleResolution::name).collect(Collectors.toList()))); + } + + public Duration getAsDuration() { + return duration; + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java index 4e059d6..ec5cd8c 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/PreparedSchedule.java @@ -14,26 +14,27 @@ package org.openmuc.fnn.steuerbox.scheduling; import com.beanit.iec61850bean.ServiceError; -import org.openmuc.fnn.steuerbox.IEC61850Utility; +import org.openmuc.fnn.steuerbox.testutils.ScheduleWriter; import java.io.IOException; import java.time.Duration; import java.time.Instant; +import java.util.List; /** * A schedule, ready to be written to the IEC 61850 device */ -public interface PreparedSchedule { +public interface PreparedSchedule { /** * Writes and enables the schedule on the device */ - void writeAndEnable(IEC61850Utility utility) throws ServiceError, IOException; + void writeAndEnable(ScheduleWriter utility) throws ServiceError, IOException; /** - * Representation of schedule values ready to be written to the 61850 server. Implementations of {@link - * PreparedScheduleValues} are available in {@link ValueAccess}. + * Representation of schedule values ready to be written to the 61850 server. Implementations of + * {@link PreparedScheduleValues} are available in {@link ValueAccess}. */ - interface PreparedScheduleValues { + interface PreparedScheduleValues { void writeValues() throws ServiceError, IOException; int size(); @@ -41,5 +42,7 @@ interface PreparedScheduleValues { String getScheduleName(); PreparedSchedule asSchedule(Duration interval, Instant start, int prio); + + List getValues(); } } \ No newline at end of file diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java index 41a0268..a5fc5df 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleDefinitions.java @@ -16,6 +16,7 @@ import java.time.Duration; import java.time.Instant; import java.util.Collection; +import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,7 +33,7 @@ public interface ScheduleDefinitions { /** * Prepare a schedule to be */ - default PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, Instant start, + default PreparedSchedule prepareSchedule(List values, int scheduleNumber, Duration interval, Instant start, int prio) { ValueAccess valueAccess = getValueAccess(); return valueAccess.prepareSchedule(values, scheduleNumber, interval, start, prio); @@ -68,7 +69,7 @@ default PreparedSchedule prepareSchedule(Collection values, int scheduleNumbe T getDefaultValue(); - default Collection getDefaultValues(int numberOfValues) { + default List getDefaultValues(int numberOfValues) { if (numberOfValues < 1) { throw new IllegalArgumentException( "numberOfValues (the size of the returned collection) needs to be at least 1"); diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java index e9170a0..c557bcc 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ScheduleType.java @@ -13,7 +13,7 @@ package org.openmuc.fnn.steuerbox.scheduling; -import org.openmuc.fnn.steuerbox.IEC61850Utility; +import org.openmuc.fnn.steuerbox.testutils.IEC61850Utility; import java.util.Arrays; import java.util.Collection; diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java index d918a5e..23585f6 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/scheduling/ValueAccess.java @@ -17,7 +17,7 @@ import com.beanit.iec61850bean.BdaFloat32; import com.beanit.iec61850bean.FcModelNode; import com.beanit.iec61850bean.ServiceError; -import org.openmuc.fnn.steuerbox.IEC61850Utility; +import org.openmuc.fnn.steuerbox.testutils.IEC61850Utility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +25,8 @@ import java.time.Duration; import java.time.Instant; import java.util.Arrays; -import java.util.Collection; +import java.util.Collections; +import java.util.List; /** * Provides access to the Values that are stored inside a ScheduleDefinition. This access is using generics to support @@ -37,14 +38,13 @@ public interface ValueAccess { String getGGIOValueSuffix(); - PreparedSchedule.PreparedScheduleValues prepareWriting(Collection values, String scheduleName); + PreparedSchedule.PreparedScheduleValues prepareWriting(List values, String scheduleName); default PreparedSchedule.PreparedScheduleValues prepareWriting(T singleValue, String scheduleName) { return prepareWriting(Arrays.asList(singleValue), scheduleName); } - PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, Instant start, - int prio); + PreparedSchedule prepareSchedule(List values, int scheduleNumber, Duration interval, Instant start, int prio); /** * Write a default value to this schedule. Useful if several types of schedules are to be processed. @@ -75,16 +75,15 @@ public String getGGIOValueSuffix() { } @Override - public PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, + public PreparedSchedule prepareSchedule(List values, int scheduleNumber, Duration interval, Instant start, int prio) { return prepareWriting(values, schedule.getScheduleName(scheduleNumber)).asSchedule(interval, start, prio); } @Override - public PreparedSchedule.PreparedScheduleValues prepareWriting(Collection values, - String scheduleName) { - return new PreparedSchedule.PreparedScheduleValues() { + public PreparedSchedule.PreparedScheduleValues prepareWriting(List values, String scheduleName) { + return new PreparedSchedule.PreparedScheduleValues() { @Override public void writeValues() throws ServiceError, IOException { int index = 1; @@ -109,6 +108,11 @@ public String getScheduleName() { public PreparedSchedule asSchedule(Duration interval, Instant start, int prio) { return valueWriterToScheduleWriter(this, interval, start, prio); } + + @Override + public List getValues() { + return Collections.unmodifiableList(values); + } }; } @@ -141,14 +145,14 @@ public String getGGIOValueSuffix() { } @Override - public PreparedSchedule prepareSchedule(Collection values, int scheduleNumber, Duration interval, + public PreparedSchedule prepareSchedule(List values, int scheduleNumber, Duration interval, Instant start, int prio) { return prepareWriting(values, schedules.getScheduleName(scheduleNumber)).asSchedule(interval, start, prio); } @Override - public PreparedSchedule.PreparedScheduleValues prepareWriting(Collection values, + public PreparedSchedule.PreparedScheduleValues prepareWriting(List values, String scheduleName) { return new PreparedSchedule.PreparedScheduleValues() { @Override @@ -175,6 +179,11 @@ public String getScheduleName() { public PreparedSchedule asSchedule(Duration interval, Instant start, int prio) { return valueWriterToScheduleWriter(this, interval, start, prio); } + + @Override + public List getValues() { + return Collections.unmodifiableList(values); + } }; } diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850Utility.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/IEC61850Utility.java similarity index 88% rename from conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850Utility.java rename to conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/IEC61850Utility.java index daa4cfb..9ac2c9f 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/IEC61850Utility.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/IEC61850Utility.java @@ -11,7 +11,7 @@ * specific language governing permissions and limitations under the License. */ -package org.openmuc.fnn.steuerbox; +package org.openmuc.fnn.steuerbox.testutils; import com.beanit.iec61850bean.BasicDataAttribute; import com.beanit.iec61850bean.BdaBoolean; @@ -34,7 +34,8 @@ import com.beanit.iec61850bean.ServerModel; import com.beanit.iec61850bean.ServiceError; import org.apache.commons.io.IOUtils; -import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; +import org.openmuc.fnn.steuerbox.Context; +import org.openmuc.fnn.steuerbox.IEC61850MissconfiguredException; import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule.PreparedScheduleValues; import org.openmuc.fnn.steuerbox.scheduling.ScheduleDefinitions; import org.openmuc.fnn.steuerbox.scheduling.ScheduleEnablingErrorKind; @@ -62,10 +63,9 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -public class IEC61850Utility implements Closeable { +public class IEC61850Utility implements Closeable, ScheduleWriter { private final static Logger log = LoggerFactory.getLogger(IEC61850Utility.class); @@ -152,20 +152,8 @@ public static float readConstantSystemReservePowerFromConfigXml(String xml) } /** - * Reads the reserve schedule from the IED's 'config.xml' and returns the constant power. Throws {@link - * IEC61850MissconfiguredException} if the reserve schedule is set up to hold more than one value - */ - public float readConstantPowerFromSysResScheduleFromXML() - throws ParserConfigurationException, IOException, SAXException, IEC61850MissconfiguredException, - ServiceError { - String xml = readFileVia61850("config.xml", 10_000); - System.out.println("XML:\n" + xml); - return readConstantSystemReservePowerFromConfigXml(xml); - } - - /** - * Reads the reserve schedule from the IED Node and returns the constant power. Throws {@link - * IEC61850MissconfiguredException} if the reserve schedule is set up to hold more than one value + * Reads the reserve schedule from the IED Node and returns the constant power. Throws + * {@link IEC61850MissconfiguredException} if the reserve schedule is set up to hold more than one value */ public T readConstantValueFromSysResScheduleFromModelNode(ValueAccess valueAccess, String reserveScheduleName) throws ServiceError, IOException, IEC61850MissconfiguredException { @@ -188,35 +176,7 @@ public T readConstantValueFromSysResScheduleFromModelNode(ValueAccess val return valueAccess.readToTargetValue(node); } - public String readFileVia61850(String fileName, int readTimeoutMillis) throws ServiceError, IOException { - AtomicBoolean done = new AtomicBoolean(false); - StringBuffer buffer = new StringBuffer(); - association.getFile(fileName, (fileData, moreFollows) -> { - - buffer.append(new String(fileData)); - done.set(!moreFollows); - return moreFollows; - }); - - long end = System.currentTimeMillis() + readTimeoutMillis; - while (!done.get()) { - if (System.currentTimeMillis() < end) { - throw new IOException("Timeout exceeded"); - } - try { - Thread.sleep(500); - } catch (InterruptedException e) { - throw new IOException("interrupted", e); - } - } - - return buffer.toString(); - } - - public void writeAndEnableSchedule(PreparedSchedule preparedSchedule) throws ServiceError, IOException { - preparedSchedule.writeAndEnable(this); - } - + @Override public void writeAndEnableSchedule(PreparedScheduleValues values, Duration interval, Instant start, int prio) throws ServiceError, IOException { @@ -285,7 +245,7 @@ public void disableSchedule(String scheduleNames) throws ServiceError, IOExcepti operate((FcModelNode) disableOp.getParent().getParent()); } - protected void operate(FcModelNode node) throws ServiceError, IOException { + public void operate(FcModelNode node) throws ServiceError, IOException { try { association.operate(node); } catch (ServiceError e) { @@ -313,7 +273,7 @@ public T readGGIOOutput(ScheduleDefinitions constants) throws ServiceError, * The result list contains a list of polled values. The first value is the polled value at the start. */ public List monitor(Instant start, Duration monitoringDuration, Duration monitoringInterval, - ScheduleDefinitions constants) throws InterruptedException { + ScheduleDefinitions constants) throws InterruptedException { log.info("setting up monitoring"); if (monitoringDuration.minus(Duration.ofSeconds(1)).isNegative()) { @@ -366,7 +326,7 @@ public BasicDataAttribute setDataValues(String objectReference, Fc fc, String va } } - protected BasicDataAttribute findAndAssignValue(String objectReference, Fc fc, String value) { + public BasicDataAttribute findAndAssignValue(String objectReference, Fc fc, String value) { ModelNode node = serverModel.findModelNode(objectReference, fc); if (node == null) { throw new RuntimeException("Could not find node with name " + objectReference); @@ -435,10 +395,6 @@ else if (modelNode instanceof BdaTimestamp) { } } - public ServerModel getCachedServerModel() { - return serverModel; - } - /** * Reads the active schedule reference from the schedule controller */ @@ -466,4 +422,18 @@ public ModelNode getNode(String nodeName) { return serverModel.findModelNode(nodeName, null); } + public ModelNode getNodeWithValues(String nodeName) throws ServiceError, IOException { + ModelNode modelNode = serverModel.findModelNode(nodeName, null); + for (ModelNode child : modelNode.getChildren()) { + if (child instanceof FcModelNode) { + log.trace("getting value for {}", child.getName()); + association.getDataValues((FcModelNode) child); + } + else { + log.trace("Ignoring {}", child.getName()); + } + } + return modelNode; + } + } diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java new file mode 100644 index 0000000..3ae07a1 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java @@ -0,0 +1,189 @@ +package org.openmuc.fnn.steuerbox.testutils; + +import com.beanit.iec61850bean.ServiceError; +import com.hivemq.client.mqtt.mqtt3.Mqtt3Client; +import io.reactivex.Single; +import org.openmuc.fnn.steuerbox.mqtt.Command; +import org.openmuc.fnn.steuerbox.mqtt.Schedule; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Closeable; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import static org.openmuc.fnn.steuerbox.mqtt.ParsingUtil.scheduleToJson; + +public class MqttUtility implements Closeable, ScheduleWriter { + + public static final String SCHEDULE_TOPIC = "fledge/south-schedule"; + public static final String CMD_TOPIC = "fledge/south-command"; + + private final static Logger log = LoggerFactory.getLogger(MqttUtility.class); + private final Mqtt3Client client; + private Consumer commandConsumer = ignore("command"); + private Consumer scheduleConsumer = ignore("schedule"); + + private Consumer ignore(String itemname) { + return cmdPayload -> log.trace("ignoring {} {}", itemname, cmdPayload); + } + + public MqttUtility() throws ExecutionException, InterruptedException { + client = Mqtt3Client.builder() + .identifier("Junit conformance test started @" + Instant.now()) + .automaticReconnect() + .maxDelay(60, TimeUnit.SECONDS) + .applyAutomaticReconnect() + .serverHost("127.0.0.1") + .serverPort(1883) + .build(); + + client.toBlocking().connect(); + + client.toAsync().connectWith().simpleAuth().username("") // no user required in local container + .password("".getBytes(StandardCharsets.UTF_8)) // no password required + .applySimpleAuth().send().orTimeout(100, TimeUnit.MILLISECONDS).whenComplete((ack, throwable) -> { + if (throwable != null) { + log.warn("Unable to connect. Is the mqtt docker container running?", throwable); + } + else { + log.debug("Connected successfully"); + } + }); + + subscribeTopic(CMD_TOPIC, () -> this.commandConsumer); + subscribeTopic(SCHEDULE_TOPIC, () -> this.scheduleConsumer); + } + + private void publishSchedule(String schedule) { + String s = "hedera-requests"; + client.toBlocking().publishWith().topic(s).payload(schedule.getBytes(StandardCharsets.UTF_8)).send(); + } + + private void subscribeTopic(String topic, Supplier> payloadConsumer) + throws ExecutionException, InterruptedException { + client.toAsync().subscribeWith().topicFilter(topic).callback(payload -> { + String payloadString = new String(payload.getPayloadAsBytes()); + log.trace("Received payload '{}' on topic '{}'", payloadString, topic); + payloadConsumer.get().accept(payloadString); + }).send().get(); + } + + @Override + public void close() throws IOException { + client.toBlocking().disconnect(); + } + + public static void main(String[] args) throws InterruptedException, ExecutionException { + MqttUtility mqttClient = new MqttUtility(); + while (true) { + mqttClient.publishSchedule( + "{\"skipHedera\":true,\"direction\":\"IMPORT\",\"start\":{\"seconds\":" + Instant.now() + .plusSeconds(1) + .getEpochSecond() + + ",\"nanos\":0},\"resolution\":\"FIFTEEN_MINUTES\",\"values\":[42,1337]}"); + Thread.sleep(60_000); + } + } + + @Override + public void writeAndEnableSchedule(PreparedSchedule.PreparedScheduleValues values, Duration interval, Instant start, + int prio) throws ServiceError, IOException { + String json = scheduleToJson(values.getValues(), interval, start); + this.publishSchedule(json); + log.debug("Published schedule {}", json); + } + + public Single>> fetchScheduleUpdate(int updatesToObserve, Duration timeout) { + Instant start = Instant.now(); + List> ret = new LinkedList<>(); + scheduleConsumer = scheduleStr -> { + try { + Instant timestamp = Instant.now(); + Schedule schedule = Schedule.parse(scheduleStr); + ret.add(new Timestamped<>(schedule, timestamp)); + log.debug("added new schedule {} with ts {}", schedule, timestamp); + } catch (Exception e) { + log.error("Unable to parse schedule '{}' and add it as a result", scheduleStr, e); + } + }; + log.debug("Start fetching schedule updates @ {}", start); + ExecutorService exec = Executors.newSingleThreadExecutor(); + Future>> future = exec.submit(() -> { + while (ret.size() < updatesToObserve && Duration.between(start, Instant.now()) + .minus(timeout) + .isNegative()) { + log.trace("Sleeping"); + Thread.sleep(100); + } + log.info("Done fetching schedule updates @ {}", Instant.now()); + scheduleConsumer = ignore("schedule after fetch timed out/enough elements collected"); + return ret; + }); + return Single.fromFuture(future); + } + + public Single>> fetchCommandUpdate(int updatesToObserve, Duration timeout) { + Instant start = Instant.now(); + List> ret = new LinkedList<>(); + commandConsumer = cmdStr -> { + try { + Instant timestamp = Instant.now(); + Command command = Command.fromJsonString(cmdStr); + ret.add(new Timestamped<>(command, timestamp)); + log.debug("added new command {} with ts {}", command, timestamp); + } catch (Exception e) { + log.error("Unable to parse command '{}' and add it as a result", cmdStr, e); + } + }; + log.debug("Start fetching command updates @ {}", start); + ExecutorService exec = Executors.newSingleThreadExecutor(); + Future>> future = exec.submit(() -> { + while (ret.size() < updatesToObserve && Duration.between(start, Instant.now()) + .minus(timeout) + .isNegative()) { + log.trace("Sleeping"); + Thread.sleep(100); + } + log.info("Done fetching command updates @ {}", Instant.now()); + commandConsumer = ignore("command after fetch timed out/enough elements collected"); + return ret; + }); + return Single.fromFuture(future); + } + + public static class Timestamped { + T object; + Instant timestamp; + + public Timestamped(T object, Instant timestamp) { + this.object = object; + this.timestamp = timestamp; + } + + public T getObject() { + return object; + } + + public Instant getTimestamp() { + return timestamp; + } + + @Override + public String toString() { + return object.toString() + " timestamped @ " + timestamp.toString(); + } + } +} diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/ScheduleWriter.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/ScheduleWriter.java new file mode 100644 index 0000000..4cf1145 --- /dev/null +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/ScheduleWriter.java @@ -0,0 +1,22 @@ +package org.openmuc.fnn.steuerbox.testutils; + +import com.beanit.iec61850bean.ServiceError; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; + +/** + * Common interface for all utilities that are able to write a IEC 61850 schedule to a device + */ +public interface ScheduleWriter { + + void writeAndEnableSchedule(PreparedSchedule.PreparedScheduleValues values, Duration interval, Instant start, + int prio) throws ServiceError, IOException; + + default void writeAndEnableSchedule(PreparedSchedule preparedSchedule) throws ServiceError, IOException { + preparedSchedule.writeAndEnable(this); + } + +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java index f3090cb..2c46bc7 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java @@ -53,7 +53,7 @@ public static void connectToDUT() throws ServiceError, IOException { } @BeforeEach - public void stopAllRunningSchedules(){ + public void stopAllRunningSchedules() { disableAllRunningSchedules(); logger.debug("Disabled all schedules during init"); } @@ -94,14 +94,14 @@ protected static Stream> getAllSchedules() { return Stream.of(dut.powerSchedules, dut.maxPowerSchedules, dut.onOffSchedules); } - public static void assertValuesMatch(List expectedValues, List actualValues, double withPercentage) { + public static void assertValuesMatch(List expectedValues, List actualValues, double withPercentage) { Assertions.assertEquals(actualValues.size(), expectedValues.size()); for (int i = 0; i < expectedValues.size(); i++) { Float expected = expectedValues.get(i); - Float actual = actualValues.get(i); - Assertions.assertEquals(expected, actual,withPercentage,"Array does not match at index "+i+". " - + "\nExpected values: "+expectedValues+"" - + "\nactual values : "+actualValues+"\n"); + Float actual = actualValues.get(i).floatValue(); + Assertions.assertEquals(expected, actual, withPercentage, + "Array does not match at index " + i + ". " + "\nExpected values: " + expectedValues + "" + + "\nactual values : " + actualValues + "\n"); } } @@ -116,29 +116,31 @@ public static void assertValuesMatch(List expectedValues, List for (int i = 0; i < expectedValues.size(); i++) { boolean expected = expectedValues.get(i); boolean actual = actualValues.get(i); - Assertions.assertEquals(expected, actual,"Array does not match at index "+i+". " - + "\nExpected values: "+expectedValues+"" - + "\nactual values : "+actualValues+"\n"); + Assertions.assertEquals(expected, actual, + "Array does not match at index " + i + ". " + "\nExpected values: " + expectedValues + "" + + "\nactual values : " + actualValues + "\n"); } } - protected void assertUntypedValuesMatch(List expectedValues, List actualValues) { - if(expectedValues.size() <= 0){ - if(expectedValues.size() == 0 && actualValues.size()==0){ + if (expectedValues.size() <= 0) { + if (expectedValues.size() == 0 && actualValues.size() == 0) { } else { - Assertions.fail("Values do not match, different array sizes. Expected "+expectedValues.size()+" but got "+actualValues.size()); + Assertions.fail( + "Values do not match, different array sizes. Expected " + expectedValues.size() + " but got " + + actualValues.size()); } } if (Float.class.equals(expectedValues.get(0).getClass())) { - assertValuesMatch((List) expectedValues, (List) actualValues,0.1); + assertValuesMatch((List) expectedValues, (List) actualValues, 0.1); } else if (Boolean.class.equals(expectedValues.get(0).getClass())) { assertValuesMatch((List) expectedValues, (List) actualValues); - }else { - throw new IllegalArgumentException("Expected Float or Boolean, got:"+expectedValues.get(0).getClass()); + } + else { + throw new IllegalArgumentException("Expected Float or Boolean, got:" + expectedValues.get(0).getClass()); } } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java new file mode 100644 index 0000000..c63716f --- /dev/null +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java @@ -0,0 +1,289 @@ +package org.openmuc.fnn.steuerbox; + +import com.beanit.iec61850bean.ModelNode; +import com.beanit.iec61850bean.ServiceError; +import de.fhg.ise.testtool.utils.annotations.label.Description; +import io.reactivex.Single; +import org.junit.jupiter.api.Test; +import org.openmuc.fnn.steuerbox.mqtt.Command; +import org.openmuc.fnn.steuerbox.mqtt.Schedule; +import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; +import org.openmuc.fnn.steuerbox.testutils.MqttUtility; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.time.Duration.ofSeconds; +import static java.time.temporal.ChronoUnit.HOURS; +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +/** + * Tests covering the (MQTT) interface to a local EMS to request new schedules, the forwarding of schedules and + * commands. + *

+ * These tests are tailored and limited to max power schedules, in line with the default FLEDGE settings. + */ +public class EmsInterfacingTests extends AllianderBaseTest { + + private static final Logger log = LoggerFactory.getLogger(EmsInterfacingTests.class); + + final int defaultScheduleValue; + final MqttUtility util; + + public EmsInterfacingTests() throws ExecutionException, InterruptedException, ServiceError, IOException, + IEC61850MissconfiguredException { + defaultScheduleValue = dut.readConstantValueFromSysResScheduleFromModelNode( + dut.maxPowerSchedules.getValueAccess(), dut.maxPowerSchedules.getReserveSchedule()).intValue(); + util = new MqttUtility(); + } + + @Description("Tests that a schedule transmitted via MQTT will be forwarded to the IEC 61850 server. " + + "Makes sure that schedule values and interval are maintained. Schedule priority is fixed to 20.") + @Test + void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, InterruptedException { + final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); + final int scheduleNumber = 1; + List scheduleValues = Arrays.asList(42, 1337); + Duration scheduleInterval = Duration.ofMinutes(5); + + PreparedSchedule mqttSchedule = dut.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, + scheduleInterval, expectedStart, 200); + util.writeAndEnableSchedule(mqttSchedule); + + Thread.sleep(1_000); + + assertEquals(expectedStart, dut.getScheduleStart(dut.maxPowerSchedules.getScheduleName(scheduleNumber))); + + ModelNode node = dut.getNodeWithValues(dut.maxPowerSchedules.getScheduleName(scheduleNumber)); + String node1 = node.getChild("ValASG001").getBasicDataAttributes().get(0).getValueString(); // sollte 42 sein + assertEquals(42, Float.valueOf(node1)); + String node2 = node.getChild("ValASG002").getBasicDataAttributes().get(0).getValueString(); // sollte 1337 sein + assertEquals(1337, Float.valueOf(node2)); + String numberOfScheduleValues = node.getChild("NumEntr") + .getBasicDataAttributes() + .get(0) + .getValueString(); // sollte 2 sein! + assertEquals(2, Integer.valueOf(numberOfScheduleValues)); + + String schdIntv = node.getChild("SchdIntv") + .getBasicDataAttributes() + .get(0) + .getValueString(); // sollte 5min sein + assertEquals(scheduleInterval.toSeconds(), Long.valueOf(schdIntv)); + + String schdPrio = node.getChild("SchdPrio") + .getBasicDataAttributes() + .get(0) + .getValueString(); // sollte 20 sein, ist im hedera client hard gekodet! + assertEquals(20, Long.valueOf(schdPrio)); // given prio is ignored when transmitting via mqtt! + } + + @Description("Tests that a schedule that covers an entire day can be created and transmitted via MQTT interface.") + @Test + void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException { + + final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); + final int scheduleNumber = 1; + List scheduleValues = Stream.iterate(1, i -> i + 1) + .limit(100) + .map(i -> (Number) i) + .collect(Collectors.toList()); + Duration scheduleInterval = Duration.ofMinutes(15); + + PreparedSchedule mqttSchedule = dut.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, + scheduleInterval, expectedStart, 200); + util.writeAndEnableSchedule(mqttSchedule); + + Thread.sleep(1_000); + + ModelNode node = dut.getNodeWithValues(dut.maxPowerSchedules.getScheduleName(scheduleNumber)); + + int valuesChecked = 0; + for (int i = 1; i <= 100; i++) { + String valueAccessString = String.format("ValASG%03d", i); + assertEquals(i, + Float.valueOf(node.getChild(valueAccessString).getBasicDataAttributes().get(0).getValueString())); + log.debug("Value of node {} has expected value {}", valueAccessString, i); + valuesChecked++; + } + assertEquals(100, valuesChecked); + + String numberOfScheduleValues = node.getChild("NumEntr").getBasicDataAttributes().get(0).getValueString(); + assertEquals(100, Integer.valueOf(numberOfScheduleValues)); + log.info("Schedule value size set to {} as expected", numberOfScheduleValues); + + String schdIntv = node.getChild("SchdIntv") + .getBasicDataAttributes() + .get(0) + .getValueString(); // sollte 5min sein + assertEquals(Duration.ofMinutes(15).toSeconds(), Long.valueOf(schdIntv)); + + Duration maximalScheduleDuration = Duration.ofMinutes(15).multipliedBy(100); + assertFalse(maximalScheduleDuration.minus(Duration.ofDays(1)).isNegative()); + log.info("Maximal schedule duration of {} is larger than 1 day (24h)", maximalScheduleDuration); + } + + @Description("This test covers: Schedules are published via MQTT. " + "Publishing interval is 5 seconds. " + + "Format of the MQTT JSON payload is as expected. " + + "Schedule values and schedule timestamps have the expected values. " + + "Does not check 'FractionOfSecond' of published schedule.") + @Test + void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, InterruptedException { + + Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); + List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); + Duration iec61850ScheduleInterval = ofSeconds(1); + PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + iec61850ScheduleValues,// + 1,// fixed for the test: fledge setup tested and set up for this schedule + iec61850ScheduleInterval,// + iec61850ScheduleStart,// + 200);// schedule prio is arbitrary, needs to be something larger than default prio + dut.writeAndEnableSchedule(iec61850schedule); + Single>> result = util.fetchScheduleUpdate(1, + Duration.between(Instant.now(), iec61850ScheduleStart).plus(iec61850ScheduleInterval.multipliedBy(2))); + log.debug("Schedule written, awaiting publishing of result schedule (happens every 5 seconds))"); + List> timestampedObjects = result.blockingGet(); + + Schedule sched = timestampedObjects.get(0).getObject(); + + log.debug("Checking schedule {}", sched); + assertEquals(defaultScheduleValue, sched.getScheduleEntries().get(0).controlValue); + + assertEquals(1d, sched.getScheduleEntries().get(1).controlValue); + assertEquals(iec61850ScheduleValues.get(0), sched.getScheduleEntries().get(1).controlValue); + assertEquals(iec61850ScheduleStart.getEpochSecond(), sched.getScheduleEntries().get(1).startEpochSecond); + + assertEquals(42d, sched.getScheduleEntries().get(2).controlValue); + assertEquals(iec61850ScheduleValues.get(1), sched.getScheduleEntries().get(2).controlValue); + assertEquals(iec61850ScheduleStart.plus(iec61850ScheduleInterval).getEpochSecond(), + sched.getScheduleEntries().get(2).startEpochSecond); + + assertEquals(1337d, sched.getScheduleEntries().get(3).controlValue); + assertEquals(iec61850ScheduleValues.get(2), sched.getScheduleEntries().get(3).controlValue); + assertEquals(iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(2)).getEpochSecond(), + sched.getScheduleEntries().get(3).startEpochSecond); + + assertEquals(defaultScheduleValue, sched.getScheduleEntries().get(4).controlValue); + assertEquals(iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(3)).getEpochSecond(), + sched.getScheduleEntries().get(4).startEpochSecond); + } + + @Description("Schedules are published via MQTT. Publishing interval is 5 seconds. Schedule values and schedule timestamps have the expected values which do not change over time. Does not check 'FractionOfSecond' of published schedule.") + @Test + void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, IOException, InterruptedException { + + Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); + List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); + Duration iec61850ScheduleInterval = ofSeconds(1); + PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + iec61850ScheduleValues,// + 1,// fixed for the test: fledge setup tested and set up for this schedule + iec61850ScheduleInterval,// + iec61850ScheduleStart,// + 200);// schedule prio is arbitrary, needs to be something larger than default prio + dut.writeAndEnableSchedule(iec61850schedule); + Single>> result = util.fetchScheduleUpdate(3, + Duration.between(Instant.now(), iec61850ScheduleStart).plus(iec61850ScheduleInterval.multipliedBy(4))); + log.debug("Schedule written, awaiting publishing of result schedule (happens every 5 seconds))"); + List> timestampedObjects = result.blockingGet(); + assertEquals(3, timestampedObjects.size()); + + Instant firstTimestamp = timestampedObjects.get(0).getTimestamp().truncatedTo(SECONDS); + Schedule firstSchedule = timestampedObjects.get(0).getObject(); + Instant secondTimestamp = timestampedObjects.get(1).getTimestamp().truncatedTo(SECONDS); + Schedule secondSchedule = timestampedObjects.get(1).getObject(); + Instant thirdTimestamp = timestampedObjects.get(2).getTimestamp().truncatedTo(SECONDS); + Schedule thirdSchedule = timestampedObjects.get(2).getObject(); + + assertEquals(firstTimestamp.plus(5, SECONDS), secondTimestamp); + assertEquals(firstTimestamp.plus(10, SECONDS), thirdTimestamp); + + for (Schedule sched : Arrays.asList(firstSchedule, secondSchedule, thirdSchedule)) { + log.debug("Checking schedule {}", sched); + assertEquals(defaultScheduleValue, sched.getScheduleEntries().get(0).controlValue); + + assertEquals(1d, sched.getScheduleEntries().get(1).controlValue); + assertEquals(iec61850ScheduleValues.get(0), sched.getScheduleEntries().get(1).controlValue); + assertEquals(iec61850ScheduleStart.getEpochSecond(), sched.getScheduleEntries().get(1).startEpochSecond); + + assertEquals(42d, sched.getScheduleEntries().get(2).controlValue); + assertEquals(iec61850ScheduleValues.get(1), sched.getScheduleEntries().get(2).controlValue); + assertEquals(iec61850ScheduleStart.plus(iec61850ScheduleInterval).getEpochSecond(), + sched.getScheduleEntries().get(2).startEpochSecond); + + assertEquals(1337d, sched.getScheduleEntries().get(3).controlValue); + assertEquals(iec61850ScheduleValues.get(2), sched.getScheduleEntries().get(3).controlValue); + assertEquals(iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(2)).getEpochSecond(), + sched.getScheduleEntries().get(3).startEpochSecond); + + assertEquals(defaultScheduleValue, sched.getScheduleEntries().get(4).controlValue); + assertEquals(iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(3)).getEpochSecond(), + sched.getScheduleEntries().get(4).startEpochSecond); + } + } + + // TODO: test fails, command publishing works only upon first startup as it seems (MZ: why is that?) + @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command.") + @Test + void commandsAreForwardedJustOnTime() throws ServiceError, IOException, ExecutionException, InterruptedException { + Instant iec61850ScheduleStart = Instant.now().plus(5, SECONDS).truncatedTo(SECONDS); + List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); + Duration iec61850ScheduleInterval = ofSeconds(1); + + // set up observation: watch all values from the schedule and changing back to default + final int commandUpdatesToObserve = iec61850ScheduleValues.size() + 1; + Single>> commandUpdates = util.fetchCommandUpdate(commandUpdatesToObserve, + iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) + .plus(Duration.between(Instant.now(), iec61850ScheduleStart).plus(ofSeconds(5)))); + // set up execution + PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + iec61850ScheduleValues,// + 1,// fixed for the test: fledge setup tested and set up for this schedule + iec61850ScheduleInterval,// + iec61850ScheduleStart,// + 200);// schedule prio is arbitrary, needs to be something larger than default prio + dut.writeAndEnableSchedule(iec61850schedule); + + // wait until command changes are observed + List> commands = commandUpdates.blockingGet(); + // do checks on 4 command updates: check values, publishing time of cmd and "sinceEpoch" of published payload + assertFalse(commands.isEmpty(), + "No MQTT commands where published localhost's MQTT broker @ topic " + util.CMD_TOPIC + "."); + assertEquals(4, commandUpdatesToObserve); + assertEquals(commandUpdatesToObserve, commands.size()); + + MqttUtility.Timestamped firstCmd = commands.get(0); + assertEquals(iec61850ScheduleStart, firstCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(iec61850ScheduleStart.getEpochSecond(), firstCmd.getObject().epochSecond); + assertEquals(1d, firstCmd.getObject().controlValue); + + MqttUtility.Timestamped secondCmd = commands.get(1); + Instant secondStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval); + assertEquals(secondStart, secondCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(secondStart.getEpochSecond(), secondCmd.getObject().epochSecond); + assertEquals(42d, secondCmd.getObject().controlValue); + + MqttUtility.Timestamped thirdCmd = commands.get(2); + Instant thirdStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(2)); + assertEquals(thirdStart, thirdCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(thirdStart.getEpochSecond(), thirdCmd.getObject().epochSecond); + assertEquals(1337d, thirdCmd.getObject().controlValue); + + MqttUtility.Timestamped fourthCmd = commands.get(3); + Instant fourthStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(3)); + assertEquals(fourthStart, fourthCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(fourthStart.getEpochSecond(), fourthCmd.getObject().epochSecond); + assertEquals(defaultScheduleValue, commands.get(3).getObject().controlValue); + } +} diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java index f78b846..a82e6e4 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java @@ -119,6 +119,7 @@ void checkSubnodes(ScheduleDefinitions scheduleConstants) { /** * {@ link Requirements#LN02a} */ + // TODO: fails only for maxpower schedules?! @DisplayName("activeControllerIsUpdated") @Requirements({ LN03, LN02a, LN02b, LN02c }) @ParameterizedTest(name = " running {0}") @@ -153,6 +154,7 @@ void activeControllerIsUpdated(ScheduleDefinitions scheduleConstants) "Did not return to system reserve schedule after execution time"); } + // TODO: fails only for maxpower schedules?! @DisplayName("activeControllerIsUpdatedWithScheduleOfHighestPrio") @Requirements({ LN03, E01 }) @ParameterizedTest(name = " running {0}") diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java index 7c886a8..434a3cb 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java @@ -60,6 +60,7 @@ public static void setDefaultValuesForReserveSchedules() throws ServiceError, IO log.info("Set default values for reserve schedules"); } + // TODO: fails @DisplayName("test_prioritiesPowerSchedules") @Requirements({ E02, S02, S05c, E01, LN01, S09 }) @ParameterizedTest(name = " running {0}") @@ -124,7 +125,7 @@ public void test_prioritiesPowerSchedules(ScheduleDefinitions scheduleCo List expectedValues = Arrays.asList(sysResValue, 10f, 30f, 70f, 100f, 11f, 31f, 71f, 99f, 12f, 32f, 72f, 98f, 13f, 33f, 73f, 97f, 70f, 90f, 70f, 90f, 70f, 10f, 80f, 100f, sysResValue); - List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(26), + List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(26), interval, scheduleConstants); log.info("expected values {}", expectedValues); @@ -206,6 +207,8 @@ public void test_prioritiesOnOffSchedules(ScheduleDefinitions scheduleC assertValuesMatch(expectedValues, actualValues); } + // TODO: fails + /** * concerning IEC61850 a schedule with the same prio but later start time rules out the one with this prio but * earlier start time, test for float schedules @@ -239,7 +242,7 @@ public void testSamePriosDifferentStartPowerSchedules(ScheduleDefinitions schedu List expectedValues = Arrays.asList(sysResValue, 10f, 70f, 100f, 70f, 70f, 10f, 100f, sysResValue); Instant monitoringStart = testExecutionStart.plus(ofSeconds(2)); - List actualValues = dut.monitor(monitoringStart, ofSeconds(36), ofSeconds(4), scheduleConstants); + List actualValues = dut.monitor(monitoringStart, ofSeconds(36), ofSeconds(4), scheduleConstants); log.info("expected values {}", expectedValues); log.info("observed values {}", actualValues); assertValuesMatch(expectedValues, actualValues, 0.01); @@ -283,6 +286,7 @@ public void testSamePriosDifferentStartOnOffSchedule(ScheduleDefinitions schedul * e.g. OnOffPow_FSCH04 rules put OnOffPow_FSCH10 IEC61850 does not determine a certain behavior in this case, this * is just a detail that was fixed for implementation */ + // TODO: fails @DisplayName("test_samePrioAndStartFloatSchedule") @Requirements({ S17 }) @ParameterizedTest(name = " running {0}") @@ -303,7 +307,7 @@ public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions sched dut.writeAndEnableSchedule(schedule2); List expectedValues = Arrays.asList(sysResValue, 70f, 70f, 100f, sysResValue); - List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), + List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), scheduleConstants); assertValuesMatch(expectedValues, actualValues, 0.01); } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java index 4c230d9..35b2b7f 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java @@ -18,17 +18,26 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import org.openmuc.fnn.steuerbox.models.AllianderDER; +import org.openmuc.fnn.steuerbox.mqtt.Command; +import org.openmuc.fnn.steuerbox.mqtt.Schedule; +import org.openmuc.fnn.steuerbox.mqtt.Schedule.ScheduleEntry; +import org.xml.sax.SAXException; +import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; +import java.time.Duration; +import java.time.Instant; +import java.util.Arrays; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.openmuc.fnn.steuerbox.AllianderTests.extractNumberFromLastNodeName; +import static org.openmuc.fnn.steuerbox.mqtt.ParsingUtil.scheduleToJson; public class UtilityTest { @Test void numberExtractionWorks() { - Assertions.assertEquals( - extractNumberFromLastNodeName("device4.schedule76.whatever.in.between.number123").get().intValue(), + assertEquals(extractNumberFromLastNodeName("device4.schedule76.whatever.in.between.number123").get().intValue(), 123); } @@ -50,7 +59,7 @@ public void testReserveScheduleWorksAsExpected() throws ServiceError, IOExceptio String valueBasicDataAttribute = String.format("%s.ValASG001.setMag.f", reserveScheduleName); dut.setDataValues(valueBasicDataAttribute, null, Float.toString(expectedValue)); - Assertions.assertEquals(expectedValue, + assertEquals(expectedValue, (float) dut.readConstantValueFromSysResScheduleFromModelNode(dut.powerSchedules.getValueAccess(), reserveScheduleName)); } @@ -77,7 +86,7 @@ void test_ReadingReserveScheduleFails_When2ComposedFromMoreThan1Element() throws dut.powerSchedules.getValueAccess(), reserveScheduleName); IEC61850MissconfiguredException caughtException = Assertions.assertThrows(IEC61850MissconfiguredException.class, executableThatShouldThrow); - Assertions.assertEquals( + assertEquals( "Expected exactly 1 power value in system reserve Schedule but got 2. Please reconfigure the device.", caughtException.getMessage()); @@ -85,9 +94,34 @@ void test_ReadingReserveScheduleFails_When2ComposedFromMoreThan1Element() throws @Test void removeingNumbersWorks() { - Assertions.assertEquals("asd", AllianderBaseTest.removeNumbers("asd123")); - Assertions.assertEquals(null, AllianderBaseTest.removeNumbers(null)); - Assertions.assertEquals("", AllianderBaseTest.removeNumbers("42")); - Assertions.assertEquals("no number", AllianderBaseTest.removeNumbers("no number")); + assertEquals("asd", AllianderBaseTest.removeNumbers("asd123")); + assertEquals(null, AllianderBaseTest.removeNumbers(null)); + assertEquals("", AllianderBaseTest.removeNumbers("42")); + assertEquals("no number", AllianderBaseTest.removeNumbers("no number")); + } + + @Test + void jsonCreationWorksAsExpected() { + String expectedJson = "{\"skipHedera\":true,\"direction\":\"IMPORT\",\"start\":{\"seconds\":1717600722,\"nanos\":0},\"resolution\":\"FIFTEEN_MINUTES\",\"values\":[42,1337]}"; + Instant start = Instant.ofEpochSecond(1717600722); + assertEquals(expectedJson, scheduleToJson(Arrays.asList(42, 1337), Duration.ofMinutes(15), start)); + } + + @Test + void commandIsParsedCorrectly() throws ParserConfigurationException, IOException, SAXException { + String command = "{\"operation\": \"PivotCommand\", \"parameters\": [{\"name\": \"PIVOTTC\", \"value\": {\"GTIC\": {\"ComingFrom\": \"iec61850\", \"ApcTyp\": {\"q\": {\"test\": 0}, \"t\": {\"SecondSinceEpoch\": 1717603268, \"FractionOfSecond\": 738197}, \"ctlVal\": 123.456}, \"Identifier\": \"TS1\"}}}]}"; + assertEquals(new Command(1717603268, 123.456), Command.fromJsonString(command)); + } + + @Test + void scheduleIsParsedCorrectly() { + String schedule = "{\"operation\": \"PivotSchedule\", \"parameters\": [{\"name\": \"PIVOTTC\", \"value\": {\"GTIC\": {\"ComingFrom\": \"iec61850\", \"ApcTyp\": {\"q\": {\"test\": 0}, \"t\": {\"SecondSinceEpoch\": 1718017399, \"FractionOfSecond\": 6459228}, \"ctlVal\": 10.0}, \"Identifier\": \"TS1\"}}}, {\"name\": \"PIVOTTC\", \"value\": {\"GTIC\": {\"ComingFrom\": \"iec61850\", \"ApcTyp\": {\"q\": {\"test\": 0}, \"t\": {\"SecondSinceEpoch\": 1718017401, \"FractionOfSecond\": 10921967}, \"ctlVal\": 20.0}, \"Identifier\": \"TS1\"}}}, {\"name\": \"PIVOTTC\", \"value\": {\"GTIC\": {\"ComingFrom\": \"iec61850\", \"ApcTyp\": {\"q\": {\"test\": 0}, \"t\": {\"SecondSinceEpoch\": 1718017406, \"FractionOfSecond\": 10921967}, \"ctlVal\": 30.0}, \"Identifier\": \"TS1\"}}}, {\"name\": \"PIVOTTC\", \"value\": {\"GTIC\": {\"ComingFrom\": \"iec61850\", \"ApcTyp\": {\"q\": {\"test\": 0}, \"t\": {\"SecondSinceEpoch\": 1718017411, \"FractionOfSecond\": 10921967}, \"ctlVal\": 40.0}, \"Identifier\": \"TS1\"}}}, {\"name\": \"PIVOTTC\", \"value\": {\"GTIC\": {\"ComingFrom\": \"iec61850\", \"ApcTyp\": {\"q\": {\"test\": 0}, \"t\": {\"SecondSinceEpoch\": 1718017416, \"FractionOfSecond\": 10921967}, \"ctlVal\": 0.0}, \"Identifier\": \"TS1\"}}}]}"; + Schedule expectedSchedule = new Schedule( // + new ScheduleEntry(1718017399, 10), // + new ScheduleEntry(1718017401, 20), // + new ScheduleEntry(1718017406, 30), // + new ScheduleEntry(1718017411, 40), // + new ScheduleEntry(1718017416, 0)); // + assertEquals(expectedSchedule, Schedule.parse(schedule)); } } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java index 96d4735..691c34f 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/VersionTest.java @@ -1,9 +1,12 @@ package org.openmuc.fnn.steuerbox; +import com.beanit.iec61850bean.ModelNode; +import com.beanit.iec61850bean.ServiceError; import de.fhg.ise.testtool.utils.annotations.label.Description; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.openmuc.fnn.steuerbox.models.AllianderDER; import java.io.IOException; import java.nio.file.Path; @@ -22,4 +25,21 @@ void libIecVersionMatchesExpectedVersion() throws IOException { Assertions.assertEquals(EXPECTED_LIB_IEC_61850_VERSION, versionSuffix); } + + @Description("Reads the IEC 61850 servers name plate and makes sure the correct config version is used") + @DisplayName("IEC 61850 config check") + @Test + void correctSCLFileIsInUse() throws ServiceError, IOException { + AllianderDER dut = AllianderDER.getWithDefaultSettings(); + ModelNode node = dut.getNodeWithValues("DER_Scheduler_Control/LLN0.NamPlt"); + String vendor = node.getChild("vendor").getBasicDataAttributes().get(0).getValueString(); + String swRev = node.getChild("swRev").getBasicDataAttributes().get(0).getValueString(); + String d = node.getChild("d").getBasicDataAttributes().get(0).getValueString(); + String configRev = node.getChild("configRev").getBasicDataAttributes().get(0).getValueString(); + + Assertions.assertEquals("Alliander", vendor); + Assertions.assertEquals("1.0.0", swRev); + Assertions.assertEquals("ReLevENT reference DER model", d); + Assertions.assertEquals("1", configRev); + } } From 92705743589eca7e7be2cc8586236ef3c25bdaf4 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Thu, 25 Jul 2024 11:41:34 +0200 Subject: [PATCH 06/15] Remove alternative minimal config because it is not used Signed-off-by: Daniel Werner --- .../minimal-config/configure_scheduler.sh | 7 - .../fledge/minimal-config/model.cfg | 558 -------------- .../fledge/minimal-config/model.cid | 715 ------------------ .../north_iec61850_exchanged_data.json | 18 - .../north_iec61850_protocol_stack.json | 13 - .../north_iec61850_scheduler_config.json | 36 - .../fledge/minimal-config/update-fledge.sh | 12 - 7 files changed, 1359 deletions(-) delete mode 100755 deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/configure_scheduler.sh delete mode 100644 deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cfg delete mode 100644 deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cid delete mode 100644 deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_exchanged_data.json delete mode 100644 deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_protocol_stack.json delete mode 100644 deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_scheduler_config.json delete mode 100755 deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/update-fledge.sh diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/configure_scheduler.sh b/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/configure_scheduler.sh deleted file mode 100755 index ad64b3d..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/configure_scheduler.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env bash - -curl -X PUT http://localhost:8081/fledge/category/iec61850north_c1 -d "@./north_iec61850_exchanged_data.json" >/dev/null 2>&1 -curl -X PUT http://localhost:8081/fledge/category/iec61850north_c1 -d "@./north_iec61850_protocol_stack.json" >/dev/null 2>&1 -curl -X PUT http://localhost:8081/fledge/category/iec61850north_c1 -d "@./north_iec61850_scheduler_config.json" >/dev/null 2>&1 -curl -X PUT http://localhost:8081/fledge/category/iec61850north_c1 -d '{"modelPath":"/usr/local/fledge/model.cfg"}' >/dev/null 2>&1 - diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cfg b/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cfg deleted file mode 100644 index 85205ea..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cfg +++ /dev/null @@ -1,558 +0,0 @@ -MODEL(DER_Scheduler_){ -LD(Control){ -LN(LLN0){ -DO(NamPlt 0){ -DA(vendor 0 20 5 0 0)="Alliander"; -DA(swRev 0 20 5 0 0)="1.0.0"; -DA(d 0 20 5 0 0)="DER Scheduler example"; -DA(configRev 0 20 5 0 0)="1"; -} -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(Health 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(Mod 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=0; -} -} -LN(LPHD1){ -DO(PhyNam 0){ -DA(vendor 0 20 5 0 0)="Alliander"; -DA(hwRev 0 20 5 0 0); -DA(swRev 0 20 5 0 0); -DA(serNum 0 20 5 0 0); -DA(model 0 20 5 0 0); -} -DO(PhyHealth 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(Proxy 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -} -LN(MaxPow_GGIO1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(AnOut1 0){ -DA(mxVal 0 27 1 1 0){ -DA(f 0 10 1 1 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(minVal 0 27 4 1 0){ -DA(f 0 10 4 1 0); -} -DA(maxVal 0 27 4 1 0){ -DA(f 0 10 4 1 0); -} -DA(dbRef 0 10 4 1 0); -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 27 12 0 0){ -DA(f 0 10 12 0 0); -} -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -} -LN(MaxPow_FSCC1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActSchdRef 0){ -DA(stVal 0 19 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(CtlEnt 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_GGIO1.AnOut1"; -} -DO(Schd01 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH01"; -} -DO(Schd02 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH02"; -} -DO(Schd03 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_Res_FSCH01"; -} -} -LN(MaxPow_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH02){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_Res_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0)=0; -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=1; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0)=3600; -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0)=2200.0; -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -DA(setCal 0 27 2 1 0){ -DA(occ 0 7 2 1 0); -DA(occType 0 12 2 1 0)=0; -DA(occPer 0 12 2 1 0)=0; -DA(weekDay 0 12 2 1 0); -DA(month 0 12 2 1 0); -DA(day 0 6 2 1 0); -DA(hr 0 6 2 1 0); -DA(mn 0 6 2 1 0); -} -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0)=1; -} -} -} -} diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cid b/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cid deleted file mode 100644 index e614cf7..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/model.cid +++ /dev/null @@ -1,715 +0,0 @@ - - - - - -

- - - -
- - - -
-

1,1,9999,1

-

12

-

00000001

-

0001

-

0001

-

0.0.0.0

-

255.255.255.0

-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - Alliander - - - 1.0.0 - - - 1 - - - DER Scheduler example - - - - - Ok - - - - - - - Alliander - - - - - false - - - - - - - - @Control/MaxPow_GGIO1.AnOut1 - - - - - @Control/MaxPow_FSCH01 - - - - - @Control/MaxPow_FSCH02 - - - - - @Control/MaxPow_Res_FSCH01 - - - - - - - 100 - - - - - - - 100 - - - - - - - 1 - - - - - - - - - - 3600 - - - - - 0 - - - - - - 2200 - - - - - - true - - - - - 1970-01-01T00:00:01Z - - - - Time - - - Hour - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - - - - on - - - - - - - - - - - - - - - - - on - - - - - status-only - - - - - None - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IEC 61850-8-1:2003 - - - - - - - - - IEC 61850-8-1:2003 - - - - - - - - - - - - - - - - - - - - - W - - - k - - - - - s - - - - - reserved - January - February - March - April - May - June - July - August - September - October - November - December - - - reserved - Monday - Tuesday - Wednesday - Thursday - Friday - Saturday - Sunday - - - Hour - Day - Week - Month - Year - - - Time - WeekDay - WeekOfYear - DayOfMonth - DayOfYear - - - y - z - a - f - p - n - µ - m - c - d - - da - h - k - M - G - T - P - E - Z - Y - - - - m - kg - s - A - K - mol - cd - deg - rad - sr - Gy - Bq - °C - Sv - F - C - S - H - V - ohm - J - N - Hz - lx - Lm - Wb - T - W - Pa - m² - m³ - m/s - m/s² - m³/s - m/m³ - M - kg/m³ - m²/s - W/m K - J/K - ppm - 1/s - rad/s - W/m² - J/m² - S/m - K/s - Pa/s - J/kg K - VA - Watts - VAr - phi - cos(phi) - Vs - V² - As - A² - A²t - VAh - Wh - VArh - V/Hz - Hz/s - char - char/s - kgm² - dB - J/Wh - W/s - l/s - dBm - - - not-supported - - - status-only - direct-with-normal-security - sbo-with-normal-security - direct-with-enhanced-security - sbo-with-enhanced-security - - - Not ready - Start Time required - Ready - Running - - - None - Missing valid NumEntr - Missing valid SchdIntv - Missing valid schedule values - Inconsistent values CDC - Missing valid StrTm - Other - - - on - blocked - test - test/blocked - off - - - Ok - Warning - Alarm - - - \ No newline at end of file diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_exchanged_data.json b/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_exchanged_data.json deleted file mode 100644 index 7c2fa3b..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_exchanged_data.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "exchanged_data": { - "exchanged_data": { - "datapoints": [ - { - "label": "TS1", - "protocols": [ - { - "name": "iec61850", - "objref": "DER_Scheduler_Control/MaxPow_GGIO1.AnOut1", - "cdc": "ApcTyp" - } - ] - } - ] - } - } -} \ No newline at end of file diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_protocol_stack.json b/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_protocol_stack.json deleted file mode 100644 index fb77c1b..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_protocol_stack.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "protocol_stack": { - "protocol_stack": { - "name": "iec61850scheduler", - "version": "1.0", - "transport_layer": { - "srv_ip": "0.0.0.0", - "port": 102, - "use_scheduler": true - } - } - } -} \ No newline at end of file diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_scheduler_config.json b/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_scheduler_config.json deleted file mode 100644 index 58d8525..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/north_iec61850_scheduler_config.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "scheduler_conf": { - "scheduler_conf": { - "targets": [ - { - "schedCtrlRef": "@Control/MaxPow_FSCC1", - "forwardOutput": false, - "forwardSchedule": true, - "forwardScheduleInterval": 5, - "forwardSchedulePeriod": 86400 - } - ], - "schedules": [ - { - "scheduleRef": "@Control/MaxPow_Res_FSCH01", - "enableScheduleControl": false, - "enabled": true, - "parameters": [ - { - "parameter": "SCHED_PARAM_STR_TM", - "enableWriteAccess": false - }, - { - "parameter": "SCHED_PARAM_SCHD_PRIO", - "enableWriteAccess": false - } - ] - } - ], - "storage": { - "databaseUri": "scheduler-db.json", - "parameters": [] - } - } - } -} diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/update-fledge.sh b/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/update-fledge.sh deleted file mode 100755 index e925fdb..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/minimal-config/update-fledge.sh +++ /dev/null @@ -1,12 +0,0 @@ -# Converts the supplied IEC 61850 model.cid into a CFG file that can be parsed by the underlying libiec61850 and copy it into a docker container - -#!/bin/bash - -DOCKER_CONTAINER_ID=a72a07d00a96 -# TODO: add genconfig.jar, do not reference local installation -java -jar ~/git/libiec61850/tools/model_generator/genconfig.jar model.cid model.cfg -docker cp model.cfg $DOCKER_CONTAINER_ID:/tmp -./configure_scheduler.sh -cd ../scripts -./fledge_restart.sh -cd - From 931b6e1c458ef3b9966f59f09dc7b5fe7a5b5a37 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Thu, 25 Jul 2024 11:42:11 +0200 Subject: [PATCH 07/15] Add description for potential bug Signed-off-by: Daniel Werner --- conformance-tests/00-run-single-test.sh | 4 ++++ conformance-tests/01-reproduce-error.sh | 8 ++++++++ conformance-tests/reproduce-error.md | 17 +++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100755 conformance-tests/00-run-single-test.sh create mode 100755 conformance-tests/01-reproduce-error.sh create mode 100644 conformance-tests/reproduce-error.md diff --git a/conformance-tests/00-run-single-test.sh b/conformance-tests/00-run-single-test.sh new file mode 100755 index 0000000..1b46d5e --- /dev/null +++ b/conformance-tests/00-run-single-test.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo "Test will only pass if it is run at first without as a single test." +./gradlew clean test --tests *EmsInterfacingTests.commandsAreForwardedJustOnTime diff --git a/conformance-tests/01-reproduce-error.sh b/conformance-tests/01-reproduce-error.sh new file mode 100755 index 0000000..5c13522 --- /dev/null +++ b/conformance-tests/01-reproduce-error.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +read -p "Please start fledge docker and hedera docker and press return" ignore_return_value + +echo "Running all EmsInterfacingTests. The default ordering of the test framework (junit) will cause the test 'commandsAreForwardedJustOnTime' to fail." + +./gradlew clean test --tests *EmsInterfacingTests* + diff --git a/conformance-tests/reproduce-error.md b/conformance-tests/reproduce-error.md new file mode 100644 index 0000000..86c5d2d --- /dev/null +++ b/conformance-tests/reproduce-error.md @@ -0,0 +1,17 @@ +# Error description + +The fledge south plugin will stop publishing command messages (on topic "fledge/south-command"), the framework seems to work only partially as new schedules are published (on topic "fledge/south-schedule"). + +# How to reporoduce + +- delete all existing FLEDGE docker images +- recreate FLEDGE docker image +- start FLEDGE docker image +- start hedera docker image +- run 01-reproduce-error.sh +--> 5 tests will complete, 1 will fail: EmsInterfacingTests > commandsAreForwardedJustOnTime() + +# Additional scripts +The script 00-run-single-test.sh runs only the test "EmsInterfacingTests > commandsAreForwardedJustOnTime()", which will pass on fresh builds but fail if 01-reproduce-error.sh was run just before it. + +Stragely, the FLEDGE docker seems to recover after a certain time. If t00-run-single-test.sh is run ~30 min after 01-reproduce-error.sh, it passes again. From 1d7b03551bd17366548817a49c96610b02618162 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Fri, 26 Jul 2024 13:59:21 +0200 Subject: [PATCH 08/15] Fetch updated config from DER scheduling, use this update model as reference model.cid: https://raw.githubusercontent.com/alliander-opensource/der-scheduling/71df74441aec4d87561483802b16c7ffb3e68b8a/models/der_scheduler.cid Signed-off-by: Daniel Werner --- .../fledge/scheduling-config/model.cfg | 19473 ---------------- .../fledge/scheduling-config/model.cid | 3551 ++- 2 files changed, 1774 insertions(+), 21250 deletions(-) delete mode 100644 deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cfg diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cfg b/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cfg deleted file mode 100644 index a7e739a..0000000 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cfg +++ /dev/null @@ -1,19473 +0,0 @@ -MODEL(DER_Scheduler_){ -LD(Control){ -LN(LLN0){ -DO(NamPlt 0){ -DA(vendor 0 20 5 0 0)="Alliander"; -DA(swRev 0 20 5 0 0)="1.0.0"; -DA(d 0 20 5 0 0)="DER Scheduler example"; -DA(configRev 0 20 5 0 0)="1"; -} -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(Health 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(Mod 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=0; -} -} -LN(LPHD1){ -DO(PhyNam 0){ -DA(vendor 0 20 5 0 0)="Alliander"; -DA(hwRev 0 20 5 0 0); -DA(swRev 0 20 5 0 0); -DA(serNum 0 20 5 0 0); -DA(model 0 20 5 0 0); -} -DO(PhyHealth 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(Proxy 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -} -LN(ActPow_GGIO1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(AnOut1 0){ -DA(mxVal 0 27 1 1 0){ -DA(f 0 10 1 1 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(minVal 0 27 4 1 0){ -DA(f 0 10 4 1 0); -} -DA(maxVal 0 27 4 1 0){ -DA(f 0 10 4 1 0); -} -DA(dbRef 0 10 4 1 0); -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 27 12 0 0){ -DA(f 0 10 12 0 0); -} -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -} -LN(MaxPow_GGIO1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(AnOut1 0){ -DA(mxVal 0 27 1 1 0){ -DA(f 0 10 1 1 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(minVal 0 27 4 1 0){ -DA(f 0 10 4 1 0); -} -DA(maxVal 0 27 4 1 0){ -DA(f 0 10 4 1 0); -} -DA(dbRef 0 10 4 1 0); -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 27 12 0 0){ -DA(f 0 10 12 0 0); -} -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -} -LN(OnOff_GGIO1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SPCSO1 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -} -LN(ActPow_FSCC1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActSchdRef 0){ -DA(stVal 0 19 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(CtlEnt 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_GGIO1.AnOut1"; -} -DO(Schd01 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH01"; -} -DO(Schd02 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH02"; -} -DO(Schd03 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH03"; -} -DO(Schd04 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH04"; -} -DO(Schd05 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH05"; -} -DO(Schd06 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH06"; -} -DO(Schd07 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH07"; -} -DO(Schd08 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH08"; -} -DO(Schd09 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH09"; -} -DO(Schd10 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_FSCH10"; -} -DO(Schd11 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/ActPow_Res_FSCH01"; -} -} -LN(MaxPow_FSCC1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActSchdRef 0){ -DA(stVal 0 19 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(CtlEnt 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_GGIO1.AnOut1"; -} -DO(Schd01 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH01"; -} -DO(Schd02 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH02"; -} -DO(Schd03 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH03"; -} -DO(Schd04 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH04"; -} -DO(Schd05 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH05"; -} -DO(Schd06 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH06"; -} -DO(Schd07 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH07"; -} -DO(Schd08 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH08"; -} -DO(Schd09 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH09"; -} -DO(Schd10 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_FSCH10"; -} -DO(Schd11 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/MaxPow_Res_FSCH01"; -} -} -LN(OnOff_FSCC1){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActSchdRef 0){ -DA(stVal 0 19 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(CtlEnt 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_GGIO1.SPCSO1"; -} -DO(Schd01 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH01"; -} -DO(Schd02 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH02"; -} -DO(Schd03 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH03"; -} -DO(Schd04 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH04"; -} -DO(Schd05 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH05"; -} -DO(Schd06 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH06"; -} -DO(Schd07 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH07"; -} -DO(Schd08 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH08"; -} -DO(Schd09 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH09"; -} -DO(Schd10 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_FSCH10"; -} -DO(Schd11 0){ -DA(setSrcRef 0 19 2 1 0)="@Control/OnOff_Res_FSCH01"; -} -} -LN(ActPow_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH02){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH03){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH04){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH05){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH06){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH07){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH08){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH09){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_FSCH10){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(ActPow_Res_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0)=0; -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=1; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0)=3600; -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0)=11.0; -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -DA(setCal 0 27 2 1 0){ -DA(occ 0 7 2 1 0); -DA(occType 0 12 2 1 0)=0; -DA(occPer 0 12 2 1 0)=0; -DA(weekDay 0 12 2 1 0); -DA(month 0 12 2 1 0); -DA(day 0 6 2 1 0); -DA(hr 0 6 2 1 0); -DA(mn 0 6 2 1 0)=0; -} -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0)=1; -} -} -LN(MaxPow_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH02){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH03){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH04){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH05){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH06){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH07){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH08){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH09){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_FSCH10){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(MaxPow_Res_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValMV 0){ -DA(mag 0 27 1 4 0){ -DA(f 0 10 1 4 0); -} -DA(q 0 23 1 2 0); -DA(t 0 22 1 0 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=38; -DA(multiplier 0 12 4 1 0)=3; -} -DA(d 0 20 5 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0)=0; -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=1; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0)=3600; -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValASG001 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0)=2200.0; -} -} -DO(ValASG002 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG003 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG004 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG005 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG006 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG007 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG008 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG009 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG010 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG011 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG012 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG013 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG014 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG015 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG016 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG017 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG018 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG019 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG020 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG021 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG022 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG023 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG024 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG025 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG026 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG027 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG028 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG029 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG030 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG031 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG032 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG033 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG034 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG035 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG036 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG037 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG038 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG039 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG040 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG041 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG042 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG043 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG044 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG045 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG046 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG047 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG048 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG049 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG050 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG051 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG052 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG053 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG054 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG055 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG056 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG057 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG058 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG059 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG060 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG061 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG062 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG063 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG064 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG065 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG066 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG067 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG068 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG069 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG070 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG071 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG072 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG073 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG074 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG075 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG076 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG077 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG078 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG079 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG080 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG081 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG082 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG083 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG084 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG085 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG086 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG087 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG088 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG089 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG090 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG091 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG092 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG093 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG094 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG095 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG096 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG097 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG098 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG099 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(ValASG100 0){ -DA(setMag 0 27 2 1 0){ -DA(f 0 10 2 1 0); -} -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -DA(setCal 0 27 2 1 0){ -DA(occ 0 7 2 1 0); -DA(occType 0 12 2 1 0)=0; -DA(occPer 0 12 2 1 0)=0; -DA(weekDay 0 12 2 1 0); -DA(month 0 12 2 1 0); -DA(day 0 6 2 1 0); -DA(hr 0 6 2 1 0); -DA(mn 0 6 2 1 0); -} -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0)=1; -} -} -LN(OnOff_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH02){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH03){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH04){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH05){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH06){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH07){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH08){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH09){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_FSCH10){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0); -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=100; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0); -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm02 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm03 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm04 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm05 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm06 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm07 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm08 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm09 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm10 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm11 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm12 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm13 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm14 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm15 0){ -DA(setTm 0 22 2 1 0); -} -DO(StrTm16 0){ -DA(setTm 0 22 2 1 0); -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0); -} -} -LN(OnOff_Res_FSCH01){ -DO(Beh 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdSt 0){ -DA(stVal 0 12 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEntr 0){ -DA(stVal 0 3 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ValSPS 0){ -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(ActStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(NxtStrTm 0){ -DA(stVal 0 22 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(SchdEnaErr 0){ -DA(stVal 0 12 0 1 0)=1; -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -} -DO(EnaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(DsaReq 0){ -DA(origin 0 27 0 0 0){ -DA(orCat 0 12 0 0 0); -DA(orIdent 0 13 0 0 0); -} -DA(ctlNum 0 6 0 0 0); -DA(stVal 0 0 0 1 0); -DA(q 0 23 0 2 0); -DA(t 0 22 0 0 0); -DA(ctlModel 0 12 4 1 0)=1; -DA(Oper 0 27 12 0 0){ -DA(ctlVal 0 0 12 0 0); -DA(origin 0 27 12 0 0){ -DA(orCat 0 12 12 0 0); -DA(orIdent 0 13 12 0 0); -} -DA(ctlNum 0 6 12 0 0); -DA(T 0 22 12 0 0); -DA(Test 0 0 12 0 0); -DA(Check 0 24 12 0 0); -} -} -DO(SchdPrio 0){ -DA(setVal 0 3 2 1 0)=0; -} -DO(NumEntr 0){ -DA(setVal 0 3 2 1 0)=1; -} -DO(SchdIntv 0){ -DA(setVal 0 3 2 1 0)=3600; -DA(units 0 27 4 1 0){ -DA(SIUnit 0 12 4 1 0)=4; -DA(multiplier 0 12 4 1 0); -} -} -DO(ValSPG001 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG002 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG003 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG004 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG005 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG006 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG007 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG008 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG009 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG010 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG011 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG012 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG013 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG014 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG015 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG016 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG017 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG018 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG019 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG020 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG021 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG022 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG023 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG024 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG025 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG026 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG027 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG028 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG029 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG030 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG031 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG032 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG033 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG034 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG035 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG036 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG037 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG038 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG039 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG040 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG041 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG042 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG043 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG044 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG045 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG046 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG047 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG048 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG049 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG050 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG051 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG052 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG053 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG054 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG055 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG056 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG057 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG058 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG059 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG060 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG061 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG062 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG063 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG064 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG065 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG066 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG067 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG068 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG069 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG070 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG071 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG072 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG073 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG074 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG075 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG076 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG077 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG078 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG079 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG080 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG081 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG082 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG083 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG084 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG085 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG086 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG087 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG088 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG089 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG090 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG091 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG092 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG093 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG094 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG095 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG096 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG097 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG098 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG099 0){ -DA(setVal 0 0 2 1 0); -} -DO(ValSPG100 0){ -DA(setVal 0 0 2 1 0); -} -DO(StrTm01 0){ -DA(setTm 0 22 2 1 0); -DA(setCal 0 27 2 1 0){ -DA(occ 0 7 2 1 0); -DA(occType 0 12 2 1 0)=0; -DA(occPer 0 12 2 1 0)=0; -DA(weekDay 0 12 2 1 0); -DA(month 0 12 2 1 0); -DA(day 0 6 2 1 0); -DA(hr 0 6 2 1 0); -DA(mn 0 6 2 1 0); -} -} -DO(SchdReuse 0){ -DA(setVal 0 0 2 1 0)=1; -} -} -} -} diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid b/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid index 57e8bce..d20a8de 100644 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid +++ b/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid @@ -1,1778 +1,1775 @@ - - - - - -
- - - -
- - - -
-

1,1,9999,1

-

12

-

00000001

-

0001

-

0001

-

0.0.0.0

-

255.255.255.0

-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - Alliander - - - 1.0.0 - - - 1 - - - ReLevENT reference DER model - - - - - Ok - - - - - - - Alliander - - - - - false - - - - - - - - - - @Control/ActPow_GGIO1.AnOut1 - - - - - @Control/ActPow_FSCH01 - - - - - @Control/ActPow_FSCH02 - - - - - @Control/ActPow_FSCH03 - - - - - @Control/ActPow_FSCH04 - - - - - @Control/ActPow_FSCH05 - - - - - @Control/ActPow_FSCH06 - - - - - @Control/ActPow_FSCH07 - - - - - @Control/ActPow_FSCH08 - - - - - @Control/ActPow_FSCH09 - - - - - @Control/ActPow_FSCH10 - - - - - @Control/ActPow_Res_FSCH01 - - - - - - - @Control/MaxPow_GGIO1.AnOut1 - - - - - @Control/MaxPow_FSCH01 - - - - - @Control/MaxPow_FSCH02 - - - - - @Control/MaxPow_FSCH03 - - - - - @Control/MaxPow_FSCH04 - - - - - @Control/MaxPow_FSCH05 - - - - - @Control/MaxPow_FSCH06 - - - - - @Control/MaxPow_FSCH07 - - - - - @Control/MaxPow_FSCH08 - - - - - @Control/MaxPow_FSCH09 - - - - - @Control/MaxPow_FSCH10 - - - - - @Control/MaxPow_Res_FSCH01 - - - - - - - @Control/OnOff_GGIO1.SPCSO1 - - - - - @Control/OnOff_FSCH01 - - - - - @Control/OnOff_FSCH02 - - - - - @Control/OnOff_FSCH03 - - - - - @Control/OnOff_FSCH04 - - - - - @Control/OnOff_FSCH05 - - - - - @Control/OnOff_FSCH06 - - - - - @Control/OnOff_FSCH07 - - - - - @Control/OnOff_FSCH08 - - - - - @Control/OnOff_FSCH09 - - - - - @Control/OnOff_FSCH10 - - - - - @Control/OnOff_Res_FSCH01 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 1 - - - - - - - - - - 3600 - - - - - 10 - - - - - - 11 - - - - - - true - - - - - 1970-01-01T00:00:01Z - - - - Time - - - Hour - - - 0 - - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 1 - - - - - - - - - - 3600 - - - - - 10 - - - - - - 2200 - - - - - - true - - - - - 1970-01-01T00:00:01Z - - - - Time - - - Hour - - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 100 - - - - - - - 1 - - - - - - - - - 3600 - - - - - 10 - - - - - false - - - - - true - - - - - 1970-01-01T00:00:01Z - - - - Time - - - Hour - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - - - - on - - - - - - - - - - - - - - - - - on - - - - - status-only - - - - - None - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - direct-with-normal-security - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - IEC 61850-8-1:2003 - - - - - - - - - IEC 61850-8-1:2003 - - - - - - - - - - - - - - - - - - - - - W - - - k - - - - - s - - - - - reserved - January - February - March - April - May - June - July - August - September - October - November - December - - - reserved - Monday - Tuesday - Wednesday - Thursday - Friday - Saturday - Sunday - - - Hour - Day - Week - Month - Year - - - Time - WeekDay - WeekOfYear - DayOfMonth - DayOfYear - - - y - z - a - f - p - n - µ - m - c - d - - da - h - k - M - G - T - P - E - Z - Y - - - - m - kg - s - A - K - mol - cd - deg - rad - sr - Gy - Bq - °C - Sv - F - C - S - H - V - ohm - J - N - Hz - lx - Lm - Wb - T - W - Pa - m² - m³ - m/s - m/s² - m³/s - m/m³ - M - kg/m³ - m²/s - W/m K - J/K - ppm - 1/s - rad/s - W/m² - J/m² - S/m - K/s - Pa/s - J/kg K - VA - Watts - VAr - phi - cos(phi) - Vs - V² - As - A² - A²t - VAh - Wh - VArh - V/Hz - Hz/s - char - char/s - kgm² - dB - J/Wh - W/s - l/s - dBm - - - not-supported - - - status-only - direct-with-normal-security - sbo-with-normal-security - direct-with-enhanced-security - sbo-with-enhanced-security - - - Not ready - Start Time required - Ready - Running - - - None - Missing valid NumEntr - Missing valid SchdIntv - Missing valid schedule values - Inconsistent values CDC - Missing valid StrTm - Other - - - on - blocked - test - test/blocked - off - - - Ok - Warning - Alarm - - + + +
+ + + +
+ + + +
+

1,1,9999,1

+

12

+

00000001

+

0001

+

0001

+

0.0.0.0

+

255.255.255.0

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + Alliander + + + 1.0.0 + + + 1 + + + ReLevENT reference DER model 1.0 + + + + + Ok + + + + + + + Alliander + + + + + false + + + + + + + + + + @Control/ActPow_GGIO1.AnOut1.mxVal.f + + + + + @Control/ActPow_FSCH01 + + + + + @Control/ActPow_FSCH02 + + + + + @Control/ActPow_FSCH03 + + + + + @Control/ActPow_FSCH04 + + + + + @Control/ActPow_FSCH05 + + + + + @Control/ActPow_FSCH06 + + + + + @Control/ActPow_FSCH07 + + + + + @Control/ActPow_FSCH08 + + + + + @Control/ActPow_FSCH09 + + + + + @Control/ActPow_FSCH10 + + + + + @Control/ActPow_Res_FSCH01 + + + + + + + @Control/MaxPow_GGIO1.AnOut1.mxVal.f + + + + + @Control/MaxPow_FSCH01 + + + + + @Control/MaxPow_FSCH02 + + + + + @Control/MaxPow_FSCH03 + + + + + @Control/MaxPow_FSCH04 + + + + + @Control/MaxPow_FSCH05 + + + + + @Control/MaxPow_FSCH06 + + + + + @Control/MaxPow_FSCH07 + + + + + @Control/MaxPow_FSCH08 + + + + + @Control/MaxPow_FSCH09 + + + + + @Control/MaxPow_FSCH10 + + + + + @Control/MaxPow_Res_FSCH01 + + + + + + + @Control/OnOff_GGIO1.SPCSO1 + + + + + @Control/OnOff_FSCH01 + + + + + @Control/OnOff_FSCH02 + + + + + @Control/OnOff_FSCH03 + + + + + @Control/OnOff_FSCH04 + + + + + @Control/OnOff_FSCH05 + + + + + @Control/OnOff_FSCH06 + + + + + @Control/OnOff_FSCH07 + + + + + @Control/OnOff_FSCH08 + + + + + @Control/OnOff_FSCH09 + + + + + @Control/OnOff_FSCH10 + + + + + @Control/OnOff_Res_FSCH01 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 1 + + + + + + + + + + 3600 + + + + + 0 + + + + + + 11 + + + + + + true + + + + + 1970-01-01T00:00:01Z + + + + Time + + + Hour + + + 0 + + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 1 + + + + + + + + + + 3600 + + + + + 0 + + + + + + 0 + + + + + + true + + + + + 1970-01-01T00:00:01Z + + + + Time + + + Hour + + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 100 + + + + + + + 1 + + + + + + + + + 3600 + + + + + 0 + + + + + false + + + + + true + + + + + 1970-01-01T00:00:01Z + + + + Time + + + Hour + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + direct-with-normal-security + + + + + + + + + + + + + + + + direct-with-normal-security + + + + + + + + + + + + + + + + on + + + + + + + + + + + + + + + + + on + + + + + status-only + + + + + None + + + + + + + + + + direct-with-normal-security + + + + + + + + + + + + + direct-with-normal-security + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + + + + + + + + + + + + + W + + + k + + + + + s + + + + + reserved + January + February + March + April + May + June + July + August + September + October + November + December + + + reserved + Monday + Tuesday + Wednesday + Thursday + Friday + Saturday + Sunday + + + Hour + Day + Week + Month + Year + + + Time + WeekDay + WeekOfYear + DayOfMonth + DayOfYear + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + + + not-supported + + + status-only + direct-with-normal-security + sbo-with-normal-security + direct-with-enhanced-security + sbo-with-enhanced-security + + + Not ready + Start Time required + Ready + Running + + + None + Missing valid NumEntr + Missing valid SchdIntv + Missing valid schedule values + Inconsistent values CDC + Missing valid StrTm + Other + + + on + blocked + test + test/blocked + off + + + Ok + Warning + Alarm + +
From 85b8a72b9ab9230659b65a3eab552aebc1397f37 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Fri, 26 Jul 2024 14:32:45 +0200 Subject: [PATCH 09/15] Change system reserve schedule priority to 10 Signed-off-by: Daniel Werner --- .../fledge/scheduling-config/model.cid | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid b/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid index d20a8de..f93d096 100644 --- a/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid +++ b/deployments/n61850-smqtt-ubuntu2004/fledge/scheduling-config/model.cid @@ -349,7 +349,7 @@ - 0 + 10 @@ -469,7 +469,7 @@ - 0 + 10 @@ -585,7 +585,7 @@ - 0 + 10 From 96ecb2de70c4e2f6010d44567211f84fd608b38e Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Fri, 26 Jul 2024 15:00:19 +0200 Subject: [PATCH 10/15] Rename test DUTs to clearly distinguish between MQTT and IEC61850 communication with DUT Signed-off-by: Daniel Werner --- .../fnn/steuerbox/testutils/MqttUtility.java | 2 - .../fnn/steuerbox/AllianderBaseTest.java | 28 +-- .../openmuc/fnn/steuerbox/AllianderTests.java | 28 +-- .../fnn/steuerbox/EmsInterfacingTests.java | 70 ++++--- .../ScheduleControllerNodeTests.java | 16 +- .../fnn/steuerbox/ScheduleExecutionTest.java | 96 ++++----- .../fnn/steuerbox/ScheduleNodeTests.java | 190 +++++++++--------- .../openmuc/fnn/steuerbox/UtilityTest.java | 2 + 8 files changed, 223 insertions(+), 209 deletions(-) diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java index 3ae07a1..6657c1d 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java @@ -50,8 +50,6 @@ public MqttUtility() throws ExecutionException, InterruptedException { .serverPort(1883) .build(); - client.toBlocking().connect(); - client.toAsync().connectWith().simpleAuth().username("") // no user required in local container .password("".getBytes(StandardCharsets.UTF_8)) // no password required .applySimpleAuth().send().orTimeout(100, TimeUnit.MILLISECONDS).whenComplete((ack, throwable) -> { diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java index 2c46bc7..e41f198 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java @@ -45,11 +45,11 @@ public abstract class AllianderBaseTest { private static final Logger logger = LoggerFactory.getLogger(ScheduleNodeTests.class); - protected static AllianderDER dut; + protected static AllianderDER dutAccess61850; @BeforeAll public static void connectToDUT() throws ServiceError, IOException { - dut = AllianderDER.getWithDefaultSettings(); + dutAccess61850 = AllianderDER.getWithDefaultSettings(); } @BeforeEach @@ -60,14 +60,14 @@ public void stopAllRunningSchedules() { @AfterAll public static void shutdownConnection() { - dut.close(); + dutAccess61850.close(); } public static void disableAllRunningSchedules() { getAllSchedules().forEach(scheduleType -> { scheduleType.getAllScheduleNames().forEach(schedule -> { try { - dut.disableSchedules(schedule); + dutAccess61850.disableSchedules(schedule); } catch (Exception e) { Assertions.fail("error, could not disable schedule " + schedule); logger.error("error, could not disable schedule " + schedule, e); @@ -91,7 +91,7 @@ protected static Stream> getOnOffSchedules() { } protected static Stream> getAllSchedules() { - return Stream.of(dut.powerSchedules, dut.maxPowerSchedules, dut.onOffSchedules); + return Stream.of(dutAccess61850.powerSchedules, dutAccess61850.maxPowerSchedules, dutAccess61850.onOffSchedules); } public static void assertValuesMatch(List expectedValues, List actualValues, double withPercentage) { @@ -150,8 +150,8 @@ protected Collection testMandatoryNodes(Map mandatory, Strin for (Map.Entry entry : mandatory.entrySet()) { String fullNodeName = parentNode + "." + entry.getKey(); - if (dut.nodeExists(fullNodeName)) { - ModelNode node = dut.getNode(fullNodeName); + if (dutAccess61850.nodeExists(fullNodeName)) { + ModelNode node = dutAccess61850.getNode(fullNodeName); Fc actualFc = ((FcModelNode) node).getFc(); if (!Objects.equals(entry.getValue(), actualFc)) { @@ -171,7 +171,7 @@ protected Collection testAtMostOnceNodes(Map atMostOne, Stri Collection violations = new LinkedList<>(); for (Map.Entry entry : atMostOne.entrySet()) { - ModelNode scheduleNode = dut.getNode(parentNode); + ModelNode scheduleNode = dutAccess61850.getNode(parentNode); if (scheduleNode == null) { Assertions.fail("Unable to find node " + parentNode); } @@ -195,7 +195,7 @@ protected Collection testOMulti(Map oMulti, String parentNod Collection violations = new LinkedList<>(); for (Map.Entry entry : oMulti.entrySet()) { - List occurencesThatContainKeyInName = dut.getNode(parentNode) + List occurencesThatContainKeyInName = dutAccess61850.getNode(parentNode) .getChildren() .stream()// .filter(childNode -> childNode.getName().contains(entry.getKey()))// @@ -236,7 +236,7 @@ protected Collection testMMulti(Map mMulti, String parentNod Collection violations = new LinkedList<>(); for (Map.Entry entry : mMulti.entrySet()) { - List occurencesThatContainKeyInName = dut.getNode(parentNode) + List occurencesThatContainKeyInName = dutAccess61850.getNode(parentNode) .getChildren() .stream()// .filter(childNode -> childNode.getName().contains(entry.getKey()))// @@ -293,10 +293,10 @@ protected Collection testMMultiF(Collection testOptionalNodes(Map optional, String for (Map.Entry entry : optional.entrySet()) { String fullNodeName = parentNode + "." + entry.getKey(); - if (dut.nodeExists(fullNodeName)) { - ModelNode node = dut.getNode(fullNodeName); + if (dutAccess61850.nodeExists(fullNodeName)) { + ModelNode node = dutAccess61850.getNode(fullNodeName); Fc actualFc = ((FcModelNode) node).getFc(); Fc expectedFc = entry.getValue(); diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java index 4e56b15..b336f45 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java @@ -55,7 +55,7 @@ public class AllianderTests extends AllianderBaseTest { void tenSchedulesAreSupportedPerType(ScheduleDefinitions scheduleConstants) { int j = 0; for (String scheduleName : scheduleConstants.getAllScheduleNames()) { - boolean ScheduleExistsOrNot = dut.nodeExists(scheduleName); + boolean ScheduleExistsOrNot = dutAccess61850.nodeExists(scheduleName); Assertions.assertTrue(ScheduleExistsOrNot, "Schedule " + scheduleName + " does not exist"); if (ScheduleExistsOrNot) j++; @@ -90,7 +90,7 @@ private void assert100ScheduleValuesAreSupported(ScheduleDefinitions schedule for (int i = 1; i <= 100; i++) { String numberAsStringFilledUpWithZeros = String.format("%03d", i); String valueConfigurationNode = scheduleName + valNodeName + numberAsStringFilledUpWithZeros; - boolean valueExists = dut.nodeExists(valueConfigurationNode); + boolean valueExists = dutAccess61850.nodeExists(valueConfigurationNode); Assertions.assertTrue(valueExists, "Missing node " + valueConfigurationNode); } } @@ -102,7 +102,7 @@ private void assert100ScheduleValuesAreSupported(ScheduleDefinitions schedule void scheduleSupportsTimebasedScheduling(ScheduleDefinitions scheduleConstants) { for (int i = 1; i <= 10; i++) { String aTimerNode = scheduleConstants.getScheduleName(i) + ".StrTm01"; - Assertions.assertTrue(dut.nodeExists(aTimerNode), + Assertions.assertTrue(dutAccess61850.nodeExists(aTimerNode), "Node " + aTimerNode + " does not exist. Time based scheduling is not possible without this node"); } } @@ -113,7 +113,7 @@ void scheduleSupportsTimebasedScheduling(ScheduleDefinitions scheduleConstants) @MethodSource("getAllSchedules") void allExpectedSchedulesExist(ScheduleDefinitions scheduleConstants) { for (String scheduleName : scheduleConstants.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(scheduleName), + Assertions.assertTrue(dutAccess61850.nodeExists(scheduleName), "Expected schedule " + scheduleName + " to exist but did not find it"); } } @@ -123,39 +123,39 @@ void allExpectedSchedulesExist(ScheduleDefinitions scheduleConstants) { @ParameterizedTest(name = " running {0}") @MethodSource("getAllSchedules") void reserveSchedulesExist(ScheduleDefinitions scheduleConstants) { - Assertions.assertTrue(dut.nodeExists(scheduleConstants.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(scheduleConstants.getReserveSchedule())); } @Requirements(S05a) @Test void absolutePowerValueSchedulesAreSupported() { - for (String absolutePowerValueSchedule : dut.powerSchedules.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + for (String absolutePowerValueSchedule : dutAccess61850.powerSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dutAccess61850.nodeExists(absolutePowerValueSchedule)); } } @Requirements(S05b) @Test void maxPowerValueSchedulesAreSupported() { - for (String absolutePowerValueSchedule : dut.maxPowerSchedules.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + for (String absolutePowerValueSchedule : dutAccess61850.maxPowerSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dutAccess61850.nodeExists(absolutePowerValueSchedule)); } } @Requirements(S05c) @Test void onOffSchedulesAreSupported() { - for (String absolutePowerValueSchedule : dut.onOffSchedules.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + for (String absolutePowerValueSchedule : dutAccess61850.onOffSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dutAccess61850.nodeExists(absolutePowerValueSchedule)); } } @Test @Requirements(S11) void threeReserveSchedulesExist() { - Assertions.assertTrue(dut.nodeExists(dut.onOffSchedules.getReserveSchedule())); - Assertions.assertTrue(dut.nodeExists(dut.maxPowerSchedules.getReserveSchedule())); - Assertions.assertTrue(dut.nodeExists(dut.powerSchedules.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(dutAccess61850.onOffSchedules.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(dutAccess61850.maxPowerSchedules.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(dutAccess61850.powerSchedules.getReserveSchedule())); } } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java index c63716f..47b8e5e 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java @@ -38,17 +38,19 @@ public class EmsInterfacingTests extends AllianderBaseTest { private static final Logger log = LoggerFactory.getLogger(EmsInterfacingTests.class); final int defaultScheduleValue; - final MqttUtility util; + final MqttUtility dutAccessMQTT; public EmsInterfacingTests() throws ExecutionException, InterruptedException, ServiceError, IOException, IEC61850MissconfiguredException { - defaultScheduleValue = dut.readConstantValueFromSysResScheduleFromModelNode( - dut.maxPowerSchedules.getValueAccess(), dut.maxPowerSchedules.getReserveSchedule()).intValue(); - util = new MqttUtility(); + defaultScheduleValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( + dutAccess61850.maxPowerSchedules.getValueAccess(), + dutAccess61850.maxPowerSchedules.getReserveSchedule()).intValue(); + dutAccessMQTT = new MqttUtility(); } @Description("Tests that a schedule transmitted via MQTT will be forwarded to the IEC 61850 server. " - + "Makes sure that schedule values and interval are maintained. Schedule priority is fixed to 20.") + + "Makes sure that schedule values and interval are maintained. Schedule priority is fixed to 20. " + + "For the test setup, a schedule is created using a MQTT interface, the actual tests are carried out using a IEC 61850 client.") @Test void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, InterruptedException { final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); @@ -56,15 +58,17 @@ void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, Interru List scheduleValues = Arrays.asList(42, 1337); Duration scheduleInterval = Duration.ofMinutes(5); - PreparedSchedule mqttSchedule = dut.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, + PreparedSchedule mqttSchedule = dutAccess61850.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, scheduleInterval, expectedStart, 200); - util.writeAndEnableSchedule(mqttSchedule); + dutAccessMQTT.writeAndEnableSchedule(mqttSchedule); Thread.sleep(1_000); - assertEquals(expectedStart, dut.getScheduleStart(dut.maxPowerSchedules.getScheduleName(scheduleNumber))); + assertEquals(expectedStart, + dutAccess61850.getScheduleStart(dutAccess61850.maxPowerSchedules.getScheduleName(scheduleNumber))); - ModelNode node = dut.getNodeWithValues(dut.maxPowerSchedules.getScheduleName(scheduleNumber)); + ModelNode node = dutAccess61850.getNodeWithValues( + dutAccess61850.maxPowerSchedules.getScheduleName(scheduleNumber)); String node1 = node.getChild("ValASG001").getBasicDataAttributes().get(0).getValueString(); // sollte 42 sein assertEquals(42, Float.valueOf(node1)); String node2 = node.getChild("ValASG002").getBasicDataAttributes().get(0).getValueString(); // sollte 1337 sein @@ -88,7 +92,8 @@ void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, Interru assertEquals(20, Long.valueOf(schdPrio)); // given prio is ignored when transmitting via mqtt! } - @Description("Tests that a schedule that covers an entire day can be created and transmitted via MQTT interface.") + @Description("Tests that a schedule that covers an entire day can be created and transmitted via MQTT interface." + + "For the test setup, a schedule is written using MQTT. The actual tests are carried out using a IEC 61850 client.") @Test void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException { @@ -100,13 +105,14 @@ void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException .collect(Collectors.toList()); Duration scheduleInterval = Duration.ofMinutes(15); - PreparedSchedule mqttSchedule = dut.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, + PreparedSchedule mqttSchedule = dutAccess61850.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, scheduleInterval, expectedStart, 200); - util.writeAndEnableSchedule(mqttSchedule); + dutAccessMQTT.writeAndEnableSchedule(mqttSchedule); Thread.sleep(1_000); - ModelNode node = dut.getNodeWithValues(dut.maxPowerSchedules.getScheduleName(scheduleNumber)); + ModelNode node = dutAccess61850.getNodeWithValues( + dutAccess61850.maxPowerSchedules.getScheduleName(scheduleNumber)); int valuesChecked = 0; for (int i = 1; i <= 100; i++) { @@ -136,21 +142,22 @@ void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException @Description("This test covers: Schedules are published via MQTT. " + "Publishing interval is 5 seconds. " + "Format of the MQTT JSON payload is as expected. " + "Schedule values and schedule timestamps have the expected values. " - + "Does not check 'FractionOfSecond' of published schedule.") + + "Does not check 'FractionOfSecond' of published schedule." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); Duration iec61850ScheduleInterval = ofSeconds(1); - PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// iec61850ScheduleValues,// 1,// fixed for the test: fledge setup tested and set up for this schedule iec61850ScheduleInterval,// iec61850ScheduleStart,// 200);// schedule prio is arbitrary, needs to be something larger than default prio - dut.writeAndEnableSchedule(iec61850schedule); - Single>> result = util.fetchScheduleUpdate(1, + dutAccess61850.writeAndEnableSchedule(iec61850schedule); + Single>> result = dutAccessMQTT.fetchScheduleUpdate(1, Duration.between(Instant.now(), iec61850ScheduleStart).plus(iec61850ScheduleInterval.multipliedBy(2))); log.debug("Schedule written, awaiting publishing of result schedule (happens every 5 seconds))"); List> timestampedObjects = result.blockingGet(); @@ -179,21 +186,23 @@ void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, I sched.getScheduleEntries().get(4).startEpochSecond); } - @Description("Schedules are published via MQTT. Publishing interval is 5 seconds. Schedule values and schedule timestamps have the expected values which do not change over time. Does not check 'FractionOfSecond' of published schedule.") + @Description( + "Schedules are published via MQTT. Publishing interval is 5 seconds. Schedule values and schedule timestamps have the expected values which do not change over time. Does not check 'FractionOfSecond' of published schedule." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); Duration iec61850ScheduleInterval = ofSeconds(1); - PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// iec61850ScheduleValues,// 1,// fixed for the test: fledge setup tested and set up for this schedule iec61850ScheduleInterval,// iec61850ScheduleStart,// 200);// schedule prio is arbitrary, needs to be something larger than default prio - dut.writeAndEnableSchedule(iec61850schedule); - Single>> result = util.fetchScheduleUpdate(3, + dutAccess61850.writeAndEnableSchedule(iec61850schedule); + Single>> result = dutAccessMQTT.fetchScheduleUpdate(3, Duration.between(Instant.now(), iec61850ScheduleStart).plus(iec61850ScheduleInterval.multipliedBy(4))); log.debug("Schedule written, awaiting publishing of result schedule (happens every 5 seconds))"); List> timestampedObjects = result.blockingGet(); @@ -234,34 +243,39 @@ void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, } // TODO: test fails, command publishing works only upon first startup as it seems (MZ: why is that?) - @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command.") + @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, " + + "control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on" + + " MQTT messages that are created by FLEDGE") @Test void commandsAreForwardedJustOnTime() throws ServiceError, IOException, ExecutionException, InterruptedException { + Instant iec61850ScheduleStart = Instant.now().plus(5, SECONDS).truncatedTo(SECONDS); List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); Duration iec61850ScheduleInterval = ofSeconds(1); // set up observation: watch all values from the schedule and changing back to default final int commandUpdatesToObserve = iec61850ScheduleValues.size() + 1; - Single>> commandUpdates = util.fetchCommandUpdate(commandUpdatesToObserve, - iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) + Single>> commandUpdates = dutAccessMQTT.fetchCommandUpdate( + commandUpdatesToObserve, iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) .plus(Duration.between(Instant.now(), iec61850ScheduleStart).plus(ofSeconds(5)))); // set up execution - PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// iec61850ScheduleValues,// 1,// fixed for the test: fledge setup tested and set up for this schedule iec61850ScheduleInterval,// iec61850ScheduleStart,// 200);// schedule prio is arbitrary, needs to be something larger than default prio - dut.writeAndEnableSchedule(iec61850schedule); + dutAccess61850.writeAndEnableSchedule(iec61850schedule); // wait until command changes are observed List> commands = commandUpdates.blockingGet(); // do checks on 4 command updates: check values, publishing time of cmd and "sinceEpoch" of published payload assertFalse(commands.isEmpty(), - "No MQTT commands where published localhost's MQTT broker @ topic " + util.CMD_TOPIC + "."); + "No MQTT commands where published localhost's MQTT broker @ topic " + dutAccessMQTT.CMD_TOPIC + "."); assertEquals(4, commandUpdatesToObserve); - assertEquals(commandUpdatesToObserve, commands.size()); + assertEquals(commandUpdatesToObserve, commands.size(), + "Expected exactly " + commandUpdatesToObserve + " MQTT command messages"); MqttUtility.Timestamped firstCmd = commands.get(0); assertEquals(iec61850ScheduleStart, firstCmd.getTimestamp().truncatedTo(SECONDS)); diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java index a82e6e4..bb13cc1 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java @@ -130,13 +130,13 @@ void activeControllerIsUpdated(ScheduleDefinitions scheduleConstants) //initial state: no schedule active -> reserve schedule is working //test, that ActSchdRef contains a reference of the reserve schedule - assertEquals(scheduleConstants.getReserveSchedule(), dut.readActiveSchedule(scheduleConstants.getController()), + assertEquals(scheduleConstants.getReserveSchedule(), dutAccess61850.readActiveSchedule(scheduleConstants.getController()), "Expecting reserve schedules to run in initial state"); String schedule = scheduleConstants.getScheduleName(1); //write and activate a schedule with a higher priority than the reserve schedule Instant scheduleStart = Instant.now().plus(Duration.ofSeconds(1)); - dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule), Duration.ofSeconds(2), scheduleStart, 100); while (Instant.now().isBefore(scheduleStart.plus(Duration.ofMillis(200)))) { @@ -144,13 +144,13 @@ void activeControllerIsUpdated(ScheduleDefinitions scheduleConstants) } //test, that ActSchdRef contains a reference of the active schedule - assertEquals(schedule, dut.readActiveSchedule(scheduleConstants.getController())); + assertEquals(schedule, dutAccess61850.readActiveSchedule(scheduleConstants.getController())); // wait until the active schedule finished service Thread.sleep(2000); //make sure the reserve schedule is active again - assertEquals(scheduleConstants.getReserveSchedule(), dut.readActiveSchedule(scheduleConstants.getController()), + assertEquals(scheduleConstants.getReserveSchedule(), dutAccess61850.readActiveSchedule(scheduleConstants.getController()), "Did not return to system reserve schedule after execution time"); } @@ -168,22 +168,22 @@ void activeControllerIsUpdatedWithScheduleOfHighestPrio(ScheduleDefinitions sche Instant start = Instant.now().plus(Duration.ofMillis(500)); // schedule 1 with low prio String schedule1Name = scheduleConstants.getScheduleName(1); - dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule1Name), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule1Name), Duration.ofSeconds(1), start, 20); // schedule 2 starts a bit after schedule 1 but with higher prio String schedule2Name = scheduleConstants.getScheduleName(2); - dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule2Name), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule2Name), Duration.ofSeconds(1), start.plus(Duration.ofSeconds(1)), 200); // wait until start (and a bit longer), then schedule 1 should be active long millisUntilStart = Duration.between(Instant.now(), start).toMillis(); Thread.sleep(millisUntilStart + 200); - assertEquals(dut.readActiveSchedule(scheduleConstants.getController()), schedule1Name); + assertEquals(dutAccess61850.readActiveSchedule(scheduleConstants.getController()), schedule1Name); // sleep 1s, after that schedule 2 should be active Thread.sleep(1_000); - assertEquals(dut.readActiveSchedule(scheduleConstants.getController()), schedule2Name); + assertEquals(dutAccess61850.readActiveSchedule(scheduleConstants.getController()), schedule2Name); Thread.sleep(1000); } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java index 434a3cb..1b8e91e 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java @@ -51,12 +51,12 @@ public class ScheduleExecutionTest extends AllianderBaseTest { @BeforeAll public static void setDefaultValuesForReserveSchedules() throws ServiceError, IOException { - dut.writeScheduleValues( - dut.powerSchedules.getValueAccess().prepareWriting(0, dut.powerSchedules.getReserveSchedule())); - dut.writeScheduleValues( - dut.maxPowerSchedules.getValueAccess().prepareWriting(0, dut.maxPowerSchedules.getReserveSchedule())); - dut.writeScheduleValues( - dut.onOffSchedules.getValueAccess().prepareWriting(false, dut.onOffSchedules.getReserveSchedule())); + dutAccess61850.writeScheduleValues( + dutAccess61850.powerSchedules.getValueAccess().prepareWriting(0, dutAccess61850.powerSchedules.getReserveSchedule())); + dutAccess61850.writeScheduleValues( + dutAccess61850.maxPowerSchedules.getValueAccess().prepareWriting(0, dutAccess61850.maxPowerSchedules.getReserveSchedule())); + dutAccess61850.writeScheduleValues( + dutAccess61850.onOffSchedules.getValueAccess().prepareWriting(false, dutAccess61850.onOffSchedules.getReserveSchedule())); log.info("Set default values for reserve schedules"); } @@ -75,57 +75,57 @@ public void test_prioritiesPowerSchedules(ScheduleDefinitions scheduleCo final Instant schedulesStart = testExecutionStart.plus(ofSeconds(10)); //schedule 1: - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(10, 30, 70, 100, 100, 100), 1, interval, schedulesStart.plus(interval), 25)); // schedule 2: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(11, 31, 71, 99, 99, 99), 2, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(11, 31, 71, 99, 99, 99), 2, interval, schedulesStart.plus(interval.multipliedBy(5)), 40)); // schedule 3: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(12, 32, 72, 98, 98), 3, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(12, 32, 72, 98, 98), 3, interval, schedulesStart.plus(interval.multipliedBy(9)), 60)); //schedule 4, ends after 44s: - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(13, 33, 73, 97, 97, 97, 97, 97, 97, 97), 4, interval, schedulesStart.plus(interval.multipliedBy(13)), 70)); //schedule 5, ends after 42s - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70, 70, 70, 70), 5, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70, 70, 70, 70), 5, interval, schedulesStart.plus(interval.multipliedBy(17)), 100)); //schedule 6, - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 6, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 6, interval, schedulesStart.plus(interval.multipliedBy(18)), 120)); //schedule 7, - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 7, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 7, interval, schedulesStart.plus(interval.multipliedBy(20)), 120)); //schedule 8: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(10), 8, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(10), 8, interval, schedulesStart.plus(interval.multipliedBy(22)), 80)); //schedule 9 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(80), 9, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(80), 9, interval, schedulesStart.plus(interval.multipliedBy(23)), 20)); //schedule 10 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 10, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 10, interval, schedulesStart.plus(interval.multipliedBy(24)), 11)); log.debug("Test setup took {}", Duration.between(testExecutionStart, now())); - float sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + float sysResValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()).floatValue(); List expectedValues = Arrays.asList(sysResValue, 10f, 30f, 70f, 100f, 11f, 31f, 71f, 99f, 12f, 32f, 72f, 98f, 13f, 33f, 73f, 97f, 70f, 90f, 70f, 90f, 70f, 10f, 80f, 100f, sysResValue); - List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(26), + List actualValues = dutAccess61850.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(26), interval, scheduleConstants); log.info("expected values {}", expectedValues); @@ -147,7 +147,7 @@ public void test_prioritiesOnOffSchedules(ScheduleDefinitions scheduleC final Instant testExecutionStart = now(); final Instant schedulesStart = testExecutionStart.plus(ofSeconds(5)); - boolean sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + boolean sysResValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); log.debug("Test setup took {}", Duration.between(testExecutionStart, now())); @@ -166,39 +166,39 @@ public void test_prioritiesOnOffSchedules(ScheduleDefinitions scheduleC // setting up schedules with increasing priorities, starting one after the other. exception: schedule 10 (is set up last) //schedule 1: - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(s1, s1, s1), 1, interval, schedulesStart.plus(interval), 15)); //schedule 2: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s2, s2, s2), 2, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s2, s2, s2), 2, interval, schedulesStart.plus(interval.multipliedBy(2)), 20)); //schedule 3: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s3, s3), 3, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s3, s3), 3, interval, schedulesStart.plus(interval.multipliedBy(3)), 30)); //schedule 4: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s4, s4), 4, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s4, s4), 4, interval, schedulesStart.plus(interval.multipliedBy(4)), 40)); //schedule 5: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s5, s5), 5, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s5, s5), 5, interval, schedulesStart.plus(interval.multipliedBy(5)), 50)); //schedule 6: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s6, s6), 6, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s6, s6), 6, interval, schedulesStart.plus(interval.multipliedBy(6)), 60)); //schedule 7: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s7, s7), 7, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s7, s7), 7, interval, schedulesStart.plus(interval.multipliedBy(7)), 70)); //schedule 8: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s8, s8), 8, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s8, s8), 8, interval, schedulesStart.plus(interval.multipliedBy(8)), 80)); //schedule 9: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s9), 9, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s9), 9, interval, schedulesStart.plus(interval.multipliedBy(9)), 90)); //schedule 10: starts together with schedule 9 but with lower priority. lasts longer, so is activated after schedule 9 is stopped - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s10, s10), 10, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s10, s10), 10, interval, schedulesStart.plus(interval.multipliedBy(9)), 11)); List expectedValues = Arrays.asList(sysResValue, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, sysResValue); - List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(12), + List actualValues = dutAccess61850.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(12), interval, scheduleConstants); log.info("expected values {}", expectedValues); @@ -224,25 +224,25 @@ public void testSamePriosDifferentStartPowerSchedules(ScheduleDefinitions schedu final Instant schedulesStart = testExecutionStart.plus(ofSeconds(4)); //schedule 5, start after 2s, duration 12s, Prio 40 - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(10, 10, 10, 10, 10, 10), 5, ofSeconds(4), schedulesStart, 40)); //schedule 1, start after 4s, duration 4s, Prio 40 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 100), 1, ofSeconds(4), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 100), 1, ofSeconds(4), schedulesStart.plus(ofSeconds(4)), 40)); //schedule 2, start after 8s, duration 4s, Prio 40 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70), 2, ofSeconds(4), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70), 2, ofSeconds(4), schedulesStart.plus(ofSeconds(12)), 40)); //schedule 3, start after 14s, duration 2s, Prio 60 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 3, ofSeconds(4), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 3, ofSeconds(4), schedulesStart.plus(ofSeconds(24)), 60)); - float sysResValue = (float) dut.readConstantValueFromSysResScheduleFromModelNode( + float sysResValue = (float) dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); List expectedValues = Arrays.asList(sysResValue, 10f, 70f, 100f, 70f, 70f, 10f, 100f, sysResValue); Instant monitoringStart = testExecutionStart.plus(ofSeconds(2)); - List actualValues = dut.monitor(monitoringStart, ofSeconds(36), ofSeconds(4), scheduleConstants); + List actualValues = dutAccess61850.monitor(monitoringStart, ofSeconds(36), ofSeconds(4), scheduleConstants); log.info("expected values {}", expectedValues); log.info("observed values {}", actualValues); assertValuesMatch(expectedValues, actualValues, 0.01); @@ -263,19 +263,19 @@ public void testSamePriosDifferentStartOnOffSchedule(ScheduleDefinitions schedul final Instant schedulesStart = testExecutionStart.plus(ofSeconds(2)); //schedule 1, start after 2s, duration 6s, Prio 40 - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(true, true, true), 1, ofSeconds(2), schedulesStart, 40)); //schedule 2, start after 4s, duration 4s, Prio 40 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(false, false), 2, ofSeconds(2), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(false, false), 2, ofSeconds(2), schedulesStart.plus(ofSeconds(2)), 40)); - boolean sysResValue = (boolean) dut.readConstantValueFromSysResScheduleFromModelNode( + boolean sysResValue = (boolean) dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); List expectedValues = Arrays.asList(sysResValue, true, false, false, sysResValue); Instant monitoringStart = testExecutionStart.plus(ofSeconds(1)); - List actualValues = dut.monitor(monitoringStart, ofSeconds(10), ofSeconds(2), scheduleConstants); + List actualValues = dutAccess61850.monitor(monitoringStart, ofSeconds(10), ofSeconds(2), scheduleConstants); log.info("expected values {}", expectedValues); log.info("observed values {}", actualValues); assertValuesMatch(expectedValues, actualValues); @@ -294,7 +294,7 @@ public void testSamePriosDifferentStartOnOffSchedule(ScheduleDefinitions schedul public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, IEC61850MissconfiguredException, InterruptedException { - float sysResValue = (float) dut.readConstantValueFromSysResScheduleFromModelNode( + float sysResValue = (float) dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); Instant start = Instant.now(); @@ -303,11 +303,11 @@ public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions sched PreparedSchedule schedule2 = scheduleConstants.prepareSchedule(Arrays.asList(100f, 100f, 100f), 2, ofSeconds(3), start.plus(ofSeconds(3)), 40); - dut.writeAndEnableSchedule(schedule1); - dut.writeAndEnableSchedule(schedule2); + dutAccess61850.writeAndEnableSchedule(schedule1); + dutAccess61850.writeAndEnableSchedule(schedule2); List expectedValues = Arrays.asList(sysResValue, 70f, 70f, 100f, sysResValue); - List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), + List actualValues = dutAccess61850.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), scheduleConstants); assertValuesMatch(expectedValues, actualValues, 0.01); } @@ -323,7 +323,7 @@ public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions sched @MethodSource("getOnOffSchedules") public void test_samePrioAndStartOnOffSchedule(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, IEC61850MissconfiguredException, InterruptedException { - boolean sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + boolean sysResValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); Instant start = Instant.now(); @@ -332,11 +332,11 @@ public void test_samePrioAndStartOnOffSchedule(ScheduleDefinitions sche PreparedSchedule schedule2 = scheduleConstants.prepareSchedule(Arrays.asList(false, false, false), 2, ofSeconds(3), start.plus(ofSeconds(3)), 40); - dut.writeAndEnableSchedule(schedule1); - dut.writeAndEnableSchedule(schedule2); + dutAccess61850.writeAndEnableSchedule(schedule1); + dutAccess61850.writeAndEnableSchedule(schedule2); List expectedValues = Arrays.asList(sysResValue, true, true, false, sysResValue); - List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), + List actualValues = dutAccess61850.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), scheduleConstants); assertValuesMatch(expectedValues, actualValues); } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java index ba49117..46d8641 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java @@ -169,19 +169,19 @@ void SchdEntrIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefiniti for (String scheduleName : scheduleConstants.getAllScheduleNames()) { //disable the schedule and display the name - dut.disableSchedule(scheduleName); + dutAccess61850.disableSchedule(scheduleName); log.info(scheduleName); //check if optional SchEntr is present - boolean isPresent = dut.nodeExists(scheduleName + ".SchdEntr"); + boolean isPresent = dutAccess61850.nodeExists(scheduleName + ".SchdEntr"); if (isPresent) { //display the state of the schedule - log.info("State of the schedule: " + dut.getScheduleState(scheduleName).toString()); + log.info("State of the schedule: " + dutAccess61850.getScheduleState(scheduleName).toString()); //if state of the schedule is not RUNNING SchdEntr might be 0 - if (dut.getScheduleState(scheduleName) != ScheduleState.RUNNING) { - String notRunningSchdEntrValueAsString = dut.getNodeEntryasString(scheduleName, "SchdEntr", + if (dutAccess61850.getScheduleState(scheduleName) != ScheduleState.RUNNING) { + String notRunningSchdEntrValueAsString = dutAccess61850.getNodeEntryasString(scheduleName, "SchdEntr", "stVal"); Assertions.assertEquals("0", notRunningSchdEntrValueAsString, "SchdEntry is not 0 although schedule is not running"); @@ -191,9 +191,9 @@ void SchdEntrIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefiniti PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(8), Instant.now().plusMillis(500), 20); - dut.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); Thread.sleep(4000); - String runningSchdEntrValueAsString = dut.getNodeEntryasString(scheduleName, "SchdEntr", "stVal"); + String runningSchdEntrValueAsString = dutAccess61850.getNodeEntryasString(scheduleName, "SchdEntr", "stVal"); Assertions.assertNotEquals("0", runningSchdEntrValueAsString, "SchdEntry is 0 although schedule is running"); } @@ -239,9 +239,9 @@ void ValSpsOrValMvIsUpdatedWithCurrentlyRunningSchedule(ScheduleDefinitions< anyPriorityHigherThanReserveSchedules); // initialize: enable schedule, then disable it again - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(1500); - dut.disableSchedules(scheduleName); + dutAccess61850.disableSchedules(scheduleName); final String spsValue = "ValSPS"; final String mvValue = "ValMV"; @@ -258,17 +258,17 @@ void ValSpsOrValMvIsUpdatedWithCurrentlyRunningSchedule(ScheduleDefinitions< shouldNotExist = spsValue; } - assertTrue(dut.nodeExists(scheduleName + "." + shouldExist)); + assertTrue(dutAccess61850.nodeExists(scheduleName + "." + shouldExist)); testOptionalNodeNotPresent(scheduleConstants, shouldNotExist); - Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, shouldExist, "q")); + Assertions.assertEquals("INVALID", dutAccess61850.getNodeEntryasString(scheduleName, shouldExist, "q")); final Instant startSecondSchedule = Instant.now().plus(interval).truncatedTo(ChronoUnit.SECONDS); final Instant startMonitoring = startSecondSchedule.plus(interval.dividedBy(2)); final PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), interval, startSecondSchedule, anyPriorityHigherThanReserveSchedules); - dut.writeAndEnableSchedule(preparedSchedule); - List actualValues = dut.monitor(startMonitoring, interval, interval, scheduleConstants); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); + List actualValues = dutAccess61850.monitor(startMonitoring, interval, interval, scheduleConstants); assertUntypedValuesMatch(expectedValues, actualValues); @@ -298,28 +298,28 @@ void ValEnsIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefinitions void ActStrTmIsUpdatedProperly(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, InterruptedException { for (String scheduleName : scheduleConstants.getAllScheduleNames()) { - if (dut.nodeExists(scheduleName + ".ActStrTm")) { + if (dutAccess61850.nodeExists(scheduleName + ".ActStrTm")) { PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(2), Instant.now().plusMillis(500), 20); //initial status - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(1500); - dut.disableSchedules(scheduleName); + dutAccess61850.disableSchedules(scheduleName); //if schedule is disabled, quality of ActStrTm should be invalid - Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, "ActStrTm", "q")); + Assertions.assertEquals("INVALID", dutAccess61850.getNodeEntryasString(scheduleName, "ActStrTm", "q")); //if schedule is active, ActStrTm.stVal should have the timestamp the active schedule started Instant timestamp = Instant.now().plusSeconds(2).truncatedTo(ChronoUnit.SECONDS); PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(4), timestamp, 20); - dut.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); Thread.sleep(3000); Assertions.assertEquals(timestamp.toString(), - dut.getNodeEntryasString(scheduleName, "ActStrTm", "stVal")); + dutAccess61850.getNodeEntryasString(scheduleName, "ActStrTm", "stVal")); } } } @@ -333,20 +333,20 @@ void NxtStrTmIsUpdatedProperly(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, InterruptedException { for (String scheduleName : scheduleConstants.getAllScheduleNames()) { // disable the schedule such that there is no planned execution - dut.disableSchedules(scheduleName); + dutAccess61850.disableSchedules(scheduleName); // no planned execution -> NxtStrTm quality should be "INVALID" - Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); + Assertions.assertEquals("INVALID", dutAccess61850.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); // create a schedule in future such that we have a planned execution Instant timestamp = Instant.now().plusSeconds(10).truncatedTo(ChronoUnit.SECONDS); PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(2), timestamp, 200); - dut.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); //if schedule is active, ActStrTm.stVal should have the timestamp the active schedule started and NxtStrTm quality should be "GOOD" - Assertions.assertEquals(timestamp.toString(), dut.getNodeEntryasString(scheduleName, "NxtStrTm", "stVal")); - Assertions.assertEquals("GOOD", dut.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); + Assertions.assertEquals(timestamp.toString(), dutAccess61850.getNodeEntryasString(scheduleName, "NxtStrTm", "stVal")); + Assertions.assertEquals("GOOD", dutAccess61850.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); } } @@ -364,22 +364,22 @@ void EnaReq_operating(ScheduleDefinitions scheduleConstants) PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(100), 100); - dut.writeAndEnableSchedule(preparedSchedule); - dut.disableSchedule(scheduleName); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.disableSchedule(scheduleName); Thread.sleep(2000); // test if intial state is correct: should be in inital state - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test 1: operating with value false should be possible the status should ignore that - BasicDataAttribute enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "false"); - dut.operate((FcModelNode) enableOp.getParent().getParent()); + BasicDataAttribute enableOp = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "false"); + dutAccess61850.operate((FcModelNode) enableOp.getParent().getParent()); // still same state: - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test2: when operating with value true on .EnaReq.Oper.ctlVal and when integrity check passes, schedule should be in ready state - enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) enableOp.getParent().getParent()); - Assertions.assertEquals(ScheduleState.READY, dut.getScheduleState(scheduleName)); + enableOp = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) enableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.READY, dutAccess61850.getScheduleState(scheduleName)); } } @@ -396,30 +396,30 @@ void DsaReq_operating(ScheduleDefinitions scheduleConstants) // intial: schedule has valid values set PreparedSchedule initialSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(initialSchedule); - dut.disableSchedule(scheduleName); + dutAccess61850.writeAndEnableSchedule(initialSchedule); + dutAccess61850.disableSchedule(scheduleName); Thread.sleep(2000); // test if initial state is correct: should be in NOT_READY - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test if operating with value false on DsaReq is ignored - BasicDataAttribute disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + BasicDataAttribute disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test, if in disabled state and operating DsaReq with true, state ist still NOT_READY - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test, if in enabled state and operating DsaReq with true, state turns into NOT_READY PreparedSchedule updatedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(5), Instant.now().plusSeconds(1), 100); - dut.writeAndEnableSchedule(updatedSchedule); - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); + dutAccess61850.writeAndEnableSchedule(updatedSchedule); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); Thread.sleep(2000); - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); } } @@ -435,23 +435,23 @@ void schdEnaErr_HoldsMISSING_VALID_NUMENTRcorrectly(ScheduleDefinitions s // intial: valid values in NumEntr, Schdintv, SchdValues and test that SchdEnaErr shows no error kind PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(200); - Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dut.getSchdEnaErr(scheduleName)); - dut.disableSchedule(scheduleName); + Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dutAccess61850.getSchdEnaErr(scheduleName)); + dutAccess61850.disableSchedule(scheduleName); // provoke error MISSING_VALID_NUMENTR by setting NumEntr = -1 - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); - BasicDataAttribute disableOp1 = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); + BasicDataAttribute disableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp1 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + BasicDataAttribute enableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); // operating will throw, we ignore that error - dut.operate((FcModelNode) disableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) disableOp1.getParent().getParent()); Executable executable1 = () -> { - dut.operate((FcModelNode) enableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) enableOp1.getParent().getParent()); }; Assertions.assertThrows(ServiceError.class, executable1); - Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_NUMENTR, dut.getSchdEnaErr(scheduleName)); + Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_NUMENTR, dutAccess61850.getSchdEnaErr(scheduleName)); } } @@ -467,23 +467,23 @@ void SchdEnaErrHoldsMISSING_VALID_SCHDINTVcorrectly(ScheduleDefinitions s // intial: valid values in NumEntr, Schdintv, SchdValues and test that SchdEnaErr shows no error kind PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(200); - Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dut.getSchdEnaErr(scheduleName)); - dut.disableSchedule(scheduleName); + Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dutAccess61850.getSchdEnaErr(scheduleName)); + dutAccess61850.disableSchedule(scheduleName); // provoke error MISSING_VALID_SCHDINTV by setting SchdIntv = -1 - dut.setDataValues(scheduleName + ".SchdIntv.setVal", null, "-1"); - BasicDataAttribute disableOp1 = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, + dutAccess61850.setDataValues(scheduleName + ".SchdIntv.setVal", null, "-1"); + BasicDataAttribute disableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp1 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + BasicDataAttribute enableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); // operating will throw, we ignore that error - dut.operate((FcModelNode) disableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) disableOp1.getParent().getParent()); Executable executable1 = () -> { - dut.operate((FcModelNode) enableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) enableOp1.getParent().getParent()); }; Assertions.assertThrows(ServiceError.class, executable1); - Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHDINTV, dut.getSchdEnaErr(scheduleName)); + Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHDINTV, dutAccess61850.getSchdEnaErr(scheduleName)); } } @@ -504,20 +504,20 @@ void SchdEnaErrHoldsMISSING_VALID_SCHEDULE_VALUEScorrectly(ScheduleDefinitions { - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule( + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule( Arrays.asList(Float.NaN, Float.MAX_VALUE, Float.POSITIVE_INFINITY), scheduleNumber, ofSeconds(2), Instant.now().plusSeconds(1), 100)); }; Assertions.assertThrows(ServiceError.class, excecutable); Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHEDULE_VALUES, - dut.getSchdEnaErr(scheduleName)); + dutAccess61850.getSchdEnaErr(scheduleName)); } } @@ -535,32 +535,32 @@ void NumEntr_range(ScheduleDefinitions scheduleConstants) // intial: valid values in NumEntr PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(200); - dut.disableSchedule(scheduleName); + dutAccess61850.disableSchedule(scheduleName); //test: 0 can not bet set to NumEtr - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "0"); - BasicDataAttribute disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Executable executable = () -> dut.operate((FcModelNode) enableOp.getParent().getParent()); + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "0"); + BasicDataAttribute disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable = () -> dutAccess61850.operate((FcModelNode) enableOp.getParent().getParent()); Assertions.assertThrows(ServiceError.class, executable); //test: -1 can not bet set to NumEtr - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp2 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Executable executable2 = () -> dut.operate((FcModelNode) enableOp2.getParent().getParent()); + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp2 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable2 = () -> dutAccess61850.operate((FcModelNode) enableOp2.getParent().getParent()); Assertions.assertThrows(ServiceError.class, executable2); //test: 200 can not bet set to NumEtr - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "200"); - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp3 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Executable executable3 = () -> dut.operate((FcModelNode) enableOp3.getParent().getParent()); + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "200"); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp3 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable3 = () -> dutAccess61850.operate((FcModelNode) enableOp3.getParent().getParent()); Assertions.assertThrows(ServiceError.class, executable3); } @@ -577,13 +577,13 @@ public void reserveSchedulesCannotBeDeactivated(ScheduleDefinitions scheduleCons // if all other schedules are deactivated, the reserve schedule should be running final String reserveSchedule = scheduleConstants.getReserveSchedule(); - Assertions.assertEquals(ScheduleState.RUNNING, dut.getScheduleState(reserveSchedule)); + Assertions.assertEquals(ScheduleState.RUNNING, dutAccess61850.getScheduleState(reserveSchedule)); try { - dut.disableSchedules(reserveSchedule); + dutAccess61850.disableSchedules(reserveSchedule); } catch (ServiceError e) { // an access violation may be thrown here, this indicates the schedule cannot be deactivated } - Assertions.assertEquals(ScheduleState.RUNNING, dut.getScheduleState(reserveSchedule)); + Assertions.assertEquals(ScheduleState.RUNNING, dutAccess61850.getScheduleState(reserveSchedule)); } @DisplayName("reserveSchedulesHaveFixedPriority") @@ -594,11 +594,11 @@ public void reserveSchedulesHaveFixedPriority(ScheduleDefinitions scheduleConsta throws ServiceError, IOException { final String reserveSchedule = scheduleConstants.getReserveSchedule(); try { - dut.setSchedulePrio(reserveSchedule, 100); + dutAccess61850.setSchedulePrio(reserveSchedule, 100); } catch (ServiceError e) { // an access violation may be thrown here, this indicates the prio cannot be changed } - Assertions.assertEquals(10, dut.readSchedulePrio(reserveSchedule)); + Assertions.assertEquals(10, dutAccess61850.readSchedulePrio(reserveSchedule)); } @DisplayName("reserveSchedulesHaveFixedStart") @@ -607,13 +607,13 @@ public void reserveSchedulesHaveFixedPriority(ScheduleDefinitions scheduleConsta @Requirements(S15) public void reserveSchedulesHaveFixedStart(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException { final String reserveSchedule = scheduleConstants.getReserveSchedule(); - Assertions.assertEquals(Instant.ofEpochSecond(1), dut.getScheduleStart(reserveSchedule)); + Assertions.assertEquals(Instant.ofEpochSecond(1), dutAccess61850.getScheduleStart(reserveSchedule)); try { - dut.setScheduleStart(reserveSchedule, Instant.now()); + dutAccess61850.setScheduleStart(reserveSchedule, Instant.now()); } catch (ServiceError e) { // an access violation may be thrown here, this indicates the start date cannot be changed } - Assertions.assertEquals(Instant.ofEpochSecond(1), dut.getScheduleStart(reserveSchedule)); + Assertions.assertEquals(Instant.ofEpochSecond(1), dutAccess61850.getScheduleStart(reserveSchedule)); } /** @@ -626,7 +626,7 @@ public void reserveSchedulesHaveFixedStart(ScheduleDefinitions scheduleConstants */ private void testOptionalNodeNotPresent(ScheduleDefinitions scheduleConstants, String nodeName) { scheduleConstants.getAllScheduleNames().forEach(schedule -> { - org.junit.jupiter.api.Assertions.assertFalse(dut.nodeExists(schedule + "." + nodeName), + org.junit.jupiter.api.Assertions.assertFalse(dutAccess61850.nodeExists(schedule + "." + nodeName), "Optional node " + nodeName + " not relevant for this use case, so it should be left out (behavior cannot be tested)."); }); diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java index 35b2b7f..2a76ac2 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java @@ -15,6 +15,7 @@ import com.beanit.iec61850bean.ServiceError; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import org.openmuc.fnn.steuerbox.models.AllianderDER; @@ -33,6 +34,7 @@ import static org.openmuc.fnn.steuerbox.AllianderTests.extractNumberFromLastNodeName; import static org.openmuc.fnn.steuerbox.mqtt.ParsingUtil.scheduleToJson; +@Tag("unit") public class UtilityTest { @Test From a07073a5a46ba4ea66e671fdc181f2bd8a086277 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Fri, 26 Jul 2024 15:10:51 +0200 Subject: [PATCH 11/15] Fix command publishing test by running it first (bug for stability filed) Signed-off-by: Daniel Werner --- conformance-tests/00-run-single-test.sh | 4 - conformance-tests/01-reproduce-error.sh | 8 -- conformance-tests/reproduce-error.md | 17 --- .../fnn/steuerbox/EmsInterfacingTests.java | 128 ++++++++++-------- 4 files changed, 69 insertions(+), 88 deletions(-) delete mode 100755 conformance-tests/00-run-single-test.sh delete mode 100755 conformance-tests/01-reproduce-error.sh delete mode 100644 conformance-tests/reproduce-error.md diff --git a/conformance-tests/00-run-single-test.sh b/conformance-tests/00-run-single-test.sh deleted file mode 100755 index 1b46d5e..0000000 --- a/conformance-tests/00-run-single-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -echo "Test will only pass if it is run at first without as a single test." -./gradlew clean test --tests *EmsInterfacingTests.commandsAreForwardedJustOnTime diff --git a/conformance-tests/01-reproduce-error.sh b/conformance-tests/01-reproduce-error.sh deleted file mode 100755 index 5c13522..0000000 --- a/conformance-tests/01-reproduce-error.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -read -p "Please start fledge docker and hedera docker and press return" ignore_return_value - -echo "Running all EmsInterfacingTests. The default ordering of the test framework (junit) will cause the test 'commandsAreForwardedJustOnTime' to fail." - -./gradlew clean test --tests *EmsInterfacingTests* - diff --git a/conformance-tests/reproduce-error.md b/conformance-tests/reproduce-error.md deleted file mode 100644 index 86c5d2d..0000000 --- a/conformance-tests/reproduce-error.md +++ /dev/null @@ -1,17 +0,0 @@ -# Error description - -The fledge south plugin will stop publishing command messages (on topic "fledge/south-command"), the framework seems to work only partially as new schedules are published (on topic "fledge/south-schedule"). - -# How to reporoduce - -- delete all existing FLEDGE docker images -- recreate FLEDGE docker image -- start FLEDGE docker image -- start hedera docker image -- run 01-reproduce-error.sh ---> 5 tests will complete, 1 will fail: EmsInterfacingTests > commandsAreForwardedJustOnTime() - -# Additional scripts -The script 00-run-single-test.sh runs only the test "EmsInterfacingTests > commandsAreForwardedJustOnTime()", which will pass on fresh builds but fail if 01-reproduce-error.sh was run just before it. - -Stragely, the FLEDGE docker seems to recover after a certain time. If t00-run-single-test.sh is run ~30 min after 01-reproduce-error.sh, it passes again. diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java index 47b8e5e..862dbfb 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java @@ -4,7 +4,10 @@ import com.beanit.iec61850bean.ServiceError; import de.fhg.ise.testtool.utils.annotations.label.Description; import io.reactivex.Single; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.openmuc.fnn.steuerbox.mqtt.Command; import org.openmuc.fnn.steuerbox.mqtt.Schedule; import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; @@ -33,6 +36,7 @@ *

* These tests are tailored and limited to max power schedules, in line with the default FLEDGE settings. */ +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class EmsInterfacingTests extends AllianderBaseTest { private static final Logger log = LoggerFactory.getLogger(EmsInterfacingTests.class); @@ -48,10 +52,72 @@ public EmsInterfacingTests() throws ExecutionException, InterruptedException, Se dutAccessMQTT = new MqttUtility(); } + @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, " + + "control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on" + + " MQTT messages that are created by FLEDGE." + + "WARNING: this test only works if it is executed first, if the order is switched this is broken. This seems to be related to FLEDEGE. " + + "This behaviour is documented in https://github.com/alliander-opensource/ReLevENT/issues/20") + @Test + @Order(1) + void commandsAreForwardedJustOnTime() throws ServiceError, IOException, ExecutionException, InterruptedException { + + Instant iec61850ScheduleStart = Instant.now().plus(5, SECONDS).truncatedTo(SECONDS); + List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); + Duration iec61850ScheduleInterval = ofSeconds(1); + + // set up observation: watch all values from the schedule and changing back to default + final int commandUpdatesToObserve = iec61850ScheduleValues.size() + 1; + Single>> commandUpdates = dutAccessMQTT.fetchCommandUpdate( + commandUpdatesToObserve, iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) + .plus(Duration.between(Instant.now(), iec61850ScheduleStart).plus(ofSeconds(5)))); + // set up execution + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// + iec61850ScheduleValues,// + 1,// fixed for the test: fledge setup tested and set up for this schedule + iec61850ScheduleInterval,// + iec61850ScheduleStart,// + 200);// schedule prio is arbitrary, needs to be something larger than default prio + dutAccess61850.writeAndEnableSchedule(iec61850schedule); + + // wait until command changes are observed + List> commands = commandUpdates.blockingGet(); + // do checks on 4 command updates: check values, publishing time of cmd and "sinceEpoch" of published payload + assertFalse(commands.isEmpty(), + "No MQTT commands where published localhost's MQTT broker @ topic " + dutAccessMQTT.CMD_TOPIC + "."); + assertEquals(4, commandUpdatesToObserve); + assertEquals(commandUpdatesToObserve, commands.size(), + "Expected exactly " + commandUpdatesToObserve + " MQTT command messages"); + + MqttUtility.Timestamped firstCmd = commands.get(0); + assertEquals(iec61850ScheduleStart, firstCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(iec61850ScheduleStart.getEpochSecond(), firstCmd.getObject().epochSecond); + assertEquals(1d, firstCmd.getObject().controlValue); + + MqttUtility.Timestamped secondCmd = commands.get(1); + Instant secondStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval); + assertEquals(secondStart, secondCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(secondStart.getEpochSecond(), secondCmd.getObject().epochSecond); + assertEquals(42d, secondCmd.getObject().controlValue); + + MqttUtility.Timestamped thirdCmd = commands.get(2); + Instant thirdStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(2)); + assertEquals(thirdStart, thirdCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(thirdStart.getEpochSecond(), thirdCmd.getObject().epochSecond); + assertEquals(1337d, thirdCmd.getObject().controlValue); + + MqttUtility.Timestamped fourthCmd = commands.get(3); + Instant fourthStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(3)); + assertEquals(fourthStart, fourthCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(fourthStart.getEpochSecond(), fourthCmd.getObject().epochSecond); + assertEquals(defaultScheduleValue, commands.get(3).getObject().controlValue); + } + @Description("Tests that a schedule transmitted via MQTT will be forwarded to the IEC 61850 server. " + "Makes sure that schedule values and interval are maintained. Schedule priority is fixed to 20. " + "For the test setup, a schedule is created using a MQTT interface, the actual tests are carried out using a IEC 61850 client.") @Test + @Order(2) void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, InterruptedException { final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); final int scheduleNumber = 1; @@ -95,6 +161,7 @@ void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, Interru @Description("Tests that a schedule that covers an entire day can be created and transmitted via MQTT interface." + "For the test setup, a schedule is written using MQTT. The actual tests are carried out using a IEC 61850 client.") @Test + @Order(3) void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException { final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); @@ -145,6 +212,7 @@ void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException + "Does not check 'FractionOfSecond' of published schedule." + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test + @Order(4) void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); @@ -190,6 +258,7 @@ void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, I "Schedules are published via MQTT. Publishing interval is 5 seconds. Schedule values and schedule timestamps have the expected values which do not change over time. Does not check 'FractionOfSecond' of published schedule." + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test + @Order(5) void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); @@ -241,63 +310,4 @@ void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, sched.getScheduleEntries().get(4).startEpochSecond); } } - - // TODO: test fails, command publishing works only upon first startup as it seems (MZ: why is that?) - @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, " - + "control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command." - + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on" - + " MQTT messages that are created by FLEDGE") - @Test - void commandsAreForwardedJustOnTime() throws ServiceError, IOException, ExecutionException, InterruptedException { - - Instant iec61850ScheduleStart = Instant.now().plus(5, SECONDS).truncatedTo(SECONDS); - List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); - Duration iec61850ScheduleInterval = ofSeconds(1); - - // set up observation: watch all values from the schedule and changing back to default - final int commandUpdatesToObserve = iec61850ScheduleValues.size() + 1; - Single>> commandUpdates = dutAccessMQTT.fetchCommandUpdate( - commandUpdatesToObserve, iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) - .plus(Duration.between(Instant.now(), iec61850ScheduleStart).plus(ofSeconds(5)))); - // set up execution - PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// - iec61850ScheduleValues,// - 1,// fixed for the test: fledge setup tested and set up for this schedule - iec61850ScheduleInterval,// - iec61850ScheduleStart,// - 200);// schedule prio is arbitrary, needs to be something larger than default prio - dutAccess61850.writeAndEnableSchedule(iec61850schedule); - - // wait until command changes are observed - List> commands = commandUpdates.blockingGet(); - // do checks on 4 command updates: check values, publishing time of cmd and "sinceEpoch" of published payload - assertFalse(commands.isEmpty(), - "No MQTT commands where published localhost's MQTT broker @ topic " + dutAccessMQTT.CMD_TOPIC + "."); - assertEquals(4, commandUpdatesToObserve); - assertEquals(commandUpdatesToObserve, commands.size(), - "Expected exactly " + commandUpdatesToObserve + " MQTT command messages"); - - MqttUtility.Timestamped firstCmd = commands.get(0); - assertEquals(iec61850ScheduleStart, firstCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(iec61850ScheduleStart.getEpochSecond(), firstCmd.getObject().epochSecond); - assertEquals(1d, firstCmd.getObject().controlValue); - - MqttUtility.Timestamped secondCmd = commands.get(1); - Instant secondStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval); - assertEquals(secondStart, secondCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(secondStart.getEpochSecond(), secondCmd.getObject().epochSecond); - assertEquals(42d, secondCmd.getObject().controlValue); - - MqttUtility.Timestamped thirdCmd = commands.get(2); - Instant thirdStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(2)); - assertEquals(thirdStart, thirdCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(thirdStart.getEpochSecond(), thirdCmd.getObject().epochSecond); - assertEquals(1337d, thirdCmd.getObject().controlValue); - - MqttUtility.Timestamped fourthCmd = commands.get(3); - Instant fourthStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(3)); - assertEquals(fourthStart, fourthCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(fourthStart.getEpochSecond(), fourthCmd.getObject().epochSecond); - assertEquals(defaultScheduleValue, commands.get(3).getObject().controlValue); - } } From c9be85f0c542e08764ab0f1a81591c56e8fe2d96 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Fri, 26 Jul 2024 15:00:19 +0200 Subject: [PATCH 12/15] Rename test DUTs to clearly distinguish between MQTT and IEC61850 communication with DUT Signed-off-by: Daniel Werner --- .../fnn/steuerbox/testutils/MqttUtility.java | 2 - .../fnn/steuerbox/AllianderBaseTest.java | 28 +-- .../openmuc/fnn/steuerbox/AllianderTests.java | 28 +-- .../fnn/steuerbox/EmsInterfacingTests.java | 70 ++++--- .../ScheduleControllerNodeTests.java | 16 +- .../fnn/steuerbox/ScheduleExecutionTest.java | 96 ++++----- .../fnn/steuerbox/ScheduleNodeTests.java | 190 +++++++++--------- .../openmuc/fnn/steuerbox/UtilityTest.java | 2 + 8 files changed, 223 insertions(+), 209 deletions(-) diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java index 3ae07a1..6657c1d 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java @@ -50,8 +50,6 @@ public MqttUtility() throws ExecutionException, InterruptedException { .serverPort(1883) .build(); - client.toBlocking().connect(); - client.toAsync().connectWith().simpleAuth().username("") // no user required in local container .password("".getBytes(StandardCharsets.UTF_8)) // no password required .applySimpleAuth().send().orTimeout(100, TimeUnit.MILLISECONDS).whenComplete((ack, throwable) -> { diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java index 2c46bc7..e41f198 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java @@ -45,11 +45,11 @@ public abstract class AllianderBaseTest { private static final Logger logger = LoggerFactory.getLogger(ScheduleNodeTests.class); - protected static AllianderDER dut; + protected static AllianderDER dutAccess61850; @BeforeAll public static void connectToDUT() throws ServiceError, IOException { - dut = AllianderDER.getWithDefaultSettings(); + dutAccess61850 = AllianderDER.getWithDefaultSettings(); } @BeforeEach @@ -60,14 +60,14 @@ public void stopAllRunningSchedules() { @AfterAll public static void shutdownConnection() { - dut.close(); + dutAccess61850.close(); } public static void disableAllRunningSchedules() { getAllSchedules().forEach(scheduleType -> { scheduleType.getAllScheduleNames().forEach(schedule -> { try { - dut.disableSchedules(schedule); + dutAccess61850.disableSchedules(schedule); } catch (Exception e) { Assertions.fail("error, could not disable schedule " + schedule); logger.error("error, could not disable schedule " + schedule, e); @@ -91,7 +91,7 @@ protected static Stream> getOnOffSchedules() { } protected static Stream> getAllSchedules() { - return Stream.of(dut.powerSchedules, dut.maxPowerSchedules, dut.onOffSchedules); + return Stream.of(dutAccess61850.powerSchedules, dutAccess61850.maxPowerSchedules, dutAccess61850.onOffSchedules); } public static void assertValuesMatch(List expectedValues, List actualValues, double withPercentage) { @@ -150,8 +150,8 @@ protected Collection testMandatoryNodes(Map mandatory, Strin for (Map.Entry entry : mandatory.entrySet()) { String fullNodeName = parentNode + "." + entry.getKey(); - if (dut.nodeExists(fullNodeName)) { - ModelNode node = dut.getNode(fullNodeName); + if (dutAccess61850.nodeExists(fullNodeName)) { + ModelNode node = dutAccess61850.getNode(fullNodeName); Fc actualFc = ((FcModelNode) node).getFc(); if (!Objects.equals(entry.getValue(), actualFc)) { @@ -171,7 +171,7 @@ protected Collection testAtMostOnceNodes(Map atMostOne, Stri Collection violations = new LinkedList<>(); for (Map.Entry entry : atMostOne.entrySet()) { - ModelNode scheduleNode = dut.getNode(parentNode); + ModelNode scheduleNode = dutAccess61850.getNode(parentNode); if (scheduleNode == null) { Assertions.fail("Unable to find node " + parentNode); } @@ -195,7 +195,7 @@ protected Collection testOMulti(Map oMulti, String parentNod Collection violations = new LinkedList<>(); for (Map.Entry entry : oMulti.entrySet()) { - List occurencesThatContainKeyInName = dut.getNode(parentNode) + List occurencesThatContainKeyInName = dutAccess61850.getNode(parentNode) .getChildren() .stream()// .filter(childNode -> childNode.getName().contains(entry.getKey()))// @@ -236,7 +236,7 @@ protected Collection testMMulti(Map mMulti, String parentNod Collection violations = new LinkedList<>(); for (Map.Entry entry : mMulti.entrySet()) { - List occurencesThatContainKeyInName = dut.getNode(parentNode) + List occurencesThatContainKeyInName = dutAccess61850.getNode(parentNode) .getChildren() .stream()// .filter(childNode -> childNode.getName().contains(entry.getKey()))// @@ -293,10 +293,10 @@ protected Collection testMMultiF(Collection testOptionalNodes(Map optional, String for (Map.Entry entry : optional.entrySet()) { String fullNodeName = parentNode + "." + entry.getKey(); - if (dut.nodeExists(fullNodeName)) { - ModelNode node = dut.getNode(fullNodeName); + if (dutAccess61850.nodeExists(fullNodeName)) { + ModelNode node = dutAccess61850.getNode(fullNodeName); Fc actualFc = ((FcModelNode) node).getFc(); Fc expectedFc = entry.getValue(); diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java index 4e56b15..b336f45 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderTests.java @@ -55,7 +55,7 @@ public class AllianderTests extends AllianderBaseTest { void tenSchedulesAreSupportedPerType(ScheduleDefinitions scheduleConstants) { int j = 0; for (String scheduleName : scheduleConstants.getAllScheduleNames()) { - boolean ScheduleExistsOrNot = dut.nodeExists(scheduleName); + boolean ScheduleExistsOrNot = dutAccess61850.nodeExists(scheduleName); Assertions.assertTrue(ScheduleExistsOrNot, "Schedule " + scheduleName + " does not exist"); if (ScheduleExistsOrNot) j++; @@ -90,7 +90,7 @@ private void assert100ScheduleValuesAreSupported(ScheduleDefinitions schedule for (int i = 1; i <= 100; i++) { String numberAsStringFilledUpWithZeros = String.format("%03d", i); String valueConfigurationNode = scheduleName + valNodeName + numberAsStringFilledUpWithZeros; - boolean valueExists = dut.nodeExists(valueConfigurationNode); + boolean valueExists = dutAccess61850.nodeExists(valueConfigurationNode); Assertions.assertTrue(valueExists, "Missing node " + valueConfigurationNode); } } @@ -102,7 +102,7 @@ private void assert100ScheduleValuesAreSupported(ScheduleDefinitions schedule void scheduleSupportsTimebasedScheduling(ScheduleDefinitions scheduleConstants) { for (int i = 1; i <= 10; i++) { String aTimerNode = scheduleConstants.getScheduleName(i) + ".StrTm01"; - Assertions.assertTrue(dut.nodeExists(aTimerNode), + Assertions.assertTrue(dutAccess61850.nodeExists(aTimerNode), "Node " + aTimerNode + " does not exist. Time based scheduling is not possible without this node"); } } @@ -113,7 +113,7 @@ void scheduleSupportsTimebasedScheduling(ScheduleDefinitions scheduleConstants) @MethodSource("getAllSchedules") void allExpectedSchedulesExist(ScheduleDefinitions scheduleConstants) { for (String scheduleName : scheduleConstants.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(scheduleName), + Assertions.assertTrue(dutAccess61850.nodeExists(scheduleName), "Expected schedule " + scheduleName + " to exist but did not find it"); } } @@ -123,39 +123,39 @@ void allExpectedSchedulesExist(ScheduleDefinitions scheduleConstants) { @ParameterizedTest(name = " running {0}") @MethodSource("getAllSchedules") void reserveSchedulesExist(ScheduleDefinitions scheduleConstants) { - Assertions.assertTrue(dut.nodeExists(scheduleConstants.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(scheduleConstants.getReserveSchedule())); } @Requirements(S05a) @Test void absolutePowerValueSchedulesAreSupported() { - for (String absolutePowerValueSchedule : dut.powerSchedules.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + for (String absolutePowerValueSchedule : dutAccess61850.powerSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dutAccess61850.nodeExists(absolutePowerValueSchedule)); } } @Requirements(S05b) @Test void maxPowerValueSchedulesAreSupported() { - for (String absolutePowerValueSchedule : dut.maxPowerSchedules.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + for (String absolutePowerValueSchedule : dutAccess61850.maxPowerSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dutAccess61850.nodeExists(absolutePowerValueSchedule)); } } @Requirements(S05c) @Test void onOffSchedulesAreSupported() { - for (String absolutePowerValueSchedule : dut.onOffSchedules.getAllScheduleNames()) { - Assertions.assertTrue(dut.nodeExists(absolutePowerValueSchedule)); + for (String absolutePowerValueSchedule : dutAccess61850.onOffSchedules.getAllScheduleNames()) { + Assertions.assertTrue(dutAccess61850.nodeExists(absolutePowerValueSchedule)); } } @Test @Requirements(S11) void threeReserveSchedulesExist() { - Assertions.assertTrue(dut.nodeExists(dut.onOffSchedules.getReserveSchedule())); - Assertions.assertTrue(dut.nodeExists(dut.maxPowerSchedules.getReserveSchedule())); - Assertions.assertTrue(dut.nodeExists(dut.powerSchedules.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(dutAccess61850.onOffSchedules.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(dutAccess61850.maxPowerSchedules.getReserveSchedule())); + Assertions.assertTrue(dutAccess61850.nodeExists(dutAccess61850.powerSchedules.getReserveSchedule())); } } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java index c63716f..47b8e5e 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java @@ -38,17 +38,19 @@ public class EmsInterfacingTests extends AllianderBaseTest { private static final Logger log = LoggerFactory.getLogger(EmsInterfacingTests.class); final int defaultScheduleValue; - final MqttUtility util; + final MqttUtility dutAccessMQTT; public EmsInterfacingTests() throws ExecutionException, InterruptedException, ServiceError, IOException, IEC61850MissconfiguredException { - defaultScheduleValue = dut.readConstantValueFromSysResScheduleFromModelNode( - dut.maxPowerSchedules.getValueAccess(), dut.maxPowerSchedules.getReserveSchedule()).intValue(); - util = new MqttUtility(); + defaultScheduleValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( + dutAccess61850.maxPowerSchedules.getValueAccess(), + dutAccess61850.maxPowerSchedules.getReserveSchedule()).intValue(); + dutAccessMQTT = new MqttUtility(); } @Description("Tests that a schedule transmitted via MQTT will be forwarded to the IEC 61850 server. " - + "Makes sure that schedule values and interval are maintained. Schedule priority is fixed to 20.") + + "Makes sure that schedule values and interval are maintained. Schedule priority is fixed to 20. " + + "For the test setup, a schedule is created using a MQTT interface, the actual tests are carried out using a IEC 61850 client.") @Test void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, InterruptedException { final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); @@ -56,15 +58,17 @@ void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, Interru List scheduleValues = Arrays.asList(42, 1337); Duration scheduleInterval = Duration.ofMinutes(5); - PreparedSchedule mqttSchedule = dut.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, + PreparedSchedule mqttSchedule = dutAccess61850.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, scheduleInterval, expectedStart, 200); - util.writeAndEnableSchedule(mqttSchedule); + dutAccessMQTT.writeAndEnableSchedule(mqttSchedule); Thread.sleep(1_000); - assertEquals(expectedStart, dut.getScheduleStart(dut.maxPowerSchedules.getScheduleName(scheduleNumber))); + assertEquals(expectedStart, + dutAccess61850.getScheduleStart(dutAccess61850.maxPowerSchedules.getScheduleName(scheduleNumber))); - ModelNode node = dut.getNodeWithValues(dut.maxPowerSchedules.getScheduleName(scheduleNumber)); + ModelNode node = dutAccess61850.getNodeWithValues( + dutAccess61850.maxPowerSchedules.getScheduleName(scheduleNumber)); String node1 = node.getChild("ValASG001").getBasicDataAttributes().get(0).getValueString(); // sollte 42 sein assertEquals(42, Float.valueOf(node1)); String node2 = node.getChild("ValASG002").getBasicDataAttributes().get(0).getValueString(); // sollte 1337 sein @@ -88,7 +92,8 @@ void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, Interru assertEquals(20, Long.valueOf(schdPrio)); // given prio is ignored when transmitting via mqtt! } - @Description("Tests that a schedule that covers an entire day can be created and transmitted via MQTT interface.") + @Description("Tests that a schedule that covers an entire day can be created and transmitted via MQTT interface." + + "For the test setup, a schedule is written using MQTT. The actual tests are carried out using a IEC 61850 client.") @Test void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException { @@ -100,13 +105,14 @@ void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException .collect(Collectors.toList()); Duration scheduleInterval = Duration.ofMinutes(15); - PreparedSchedule mqttSchedule = dut.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, + PreparedSchedule mqttSchedule = dutAccess61850.maxPowerSchedules.prepareSchedule(scheduleValues, scheduleNumber, scheduleInterval, expectedStart, 200); - util.writeAndEnableSchedule(mqttSchedule); + dutAccessMQTT.writeAndEnableSchedule(mqttSchedule); Thread.sleep(1_000); - ModelNode node = dut.getNodeWithValues(dut.maxPowerSchedules.getScheduleName(scheduleNumber)); + ModelNode node = dutAccess61850.getNodeWithValues( + dutAccess61850.maxPowerSchedules.getScheduleName(scheduleNumber)); int valuesChecked = 0; for (int i = 1; i <= 100; i++) { @@ -136,21 +142,22 @@ void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException @Description("This test covers: Schedules are published via MQTT. " + "Publishing interval is 5 seconds. " + "Format of the MQTT JSON payload is as expected. " + "Schedule values and schedule timestamps have the expected values. " - + "Does not check 'FractionOfSecond' of published schedule.") + + "Does not check 'FractionOfSecond' of published schedule." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); Duration iec61850ScheduleInterval = ofSeconds(1); - PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// iec61850ScheduleValues,// 1,// fixed for the test: fledge setup tested and set up for this schedule iec61850ScheduleInterval,// iec61850ScheduleStart,// 200);// schedule prio is arbitrary, needs to be something larger than default prio - dut.writeAndEnableSchedule(iec61850schedule); - Single>> result = util.fetchScheduleUpdate(1, + dutAccess61850.writeAndEnableSchedule(iec61850schedule); + Single>> result = dutAccessMQTT.fetchScheduleUpdate(1, Duration.between(Instant.now(), iec61850ScheduleStart).plus(iec61850ScheduleInterval.multipliedBy(2))); log.debug("Schedule written, awaiting publishing of result schedule (happens every 5 seconds))"); List> timestampedObjects = result.blockingGet(); @@ -179,21 +186,23 @@ void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, I sched.getScheduleEntries().get(4).startEpochSecond); } - @Description("Schedules are published via MQTT. Publishing interval is 5 seconds. Schedule values and schedule timestamps have the expected values which do not change over time. Does not check 'FractionOfSecond' of published schedule.") + @Description( + "Schedules are published via MQTT. Publishing interval is 5 seconds. Schedule values and schedule timestamps have the expected values which do not change over time. Does not check 'FractionOfSecond' of published schedule." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); Duration iec61850ScheduleInterval = ofSeconds(1); - PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// iec61850ScheduleValues,// 1,// fixed for the test: fledge setup tested and set up for this schedule iec61850ScheduleInterval,// iec61850ScheduleStart,// 200);// schedule prio is arbitrary, needs to be something larger than default prio - dut.writeAndEnableSchedule(iec61850schedule); - Single>> result = util.fetchScheduleUpdate(3, + dutAccess61850.writeAndEnableSchedule(iec61850schedule); + Single>> result = dutAccessMQTT.fetchScheduleUpdate(3, Duration.between(Instant.now(), iec61850ScheduleStart).plus(iec61850ScheduleInterval.multipliedBy(4))); log.debug("Schedule written, awaiting publishing of result schedule (happens every 5 seconds))"); List> timestampedObjects = result.blockingGet(); @@ -234,34 +243,39 @@ void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, } // TODO: test fails, command publishing works only upon first startup as it seems (MZ: why is that?) - @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command.") + @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, " + + "control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on" + + " MQTT messages that are created by FLEDGE") @Test void commandsAreForwardedJustOnTime() throws ServiceError, IOException, ExecutionException, InterruptedException { + Instant iec61850ScheduleStart = Instant.now().plus(5, SECONDS).truncatedTo(SECONDS); List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); Duration iec61850ScheduleInterval = ofSeconds(1); // set up observation: watch all values from the schedule and changing back to default final int commandUpdatesToObserve = iec61850ScheduleValues.size() + 1; - Single>> commandUpdates = util.fetchCommandUpdate(commandUpdatesToObserve, - iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) + Single>> commandUpdates = dutAccessMQTT.fetchCommandUpdate( + commandUpdatesToObserve, iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) .plus(Duration.between(Instant.now(), iec61850ScheduleStart).plus(ofSeconds(5)))); // set up execution - PreparedSchedule iec61850schedule = dut.maxPowerSchedules.prepareSchedule(// + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// iec61850ScheduleValues,// 1,// fixed for the test: fledge setup tested and set up for this schedule iec61850ScheduleInterval,// iec61850ScheduleStart,// 200);// schedule prio is arbitrary, needs to be something larger than default prio - dut.writeAndEnableSchedule(iec61850schedule); + dutAccess61850.writeAndEnableSchedule(iec61850schedule); // wait until command changes are observed List> commands = commandUpdates.blockingGet(); // do checks on 4 command updates: check values, publishing time of cmd and "sinceEpoch" of published payload assertFalse(commands.isEmpty(), - "No MQTT commands where published localhost's MQTT broker @ topic " + util.CMD_TOPIC + "."); + "No MQTT commands where published localhost's MQTT broker @ topic " + dutAccessMQTT.CMD_TOPIC + "."); assertEquals(4, commandUpdatesToObserve); - assertEquals(commandUpdatesToObserve, commands.size()); + assertEquals(commandUpdatesToObserve, commands.size(), + "Expected exactly " + commandUpdatesToObserve + " MQTT command messages"); MqttUtility.Timestamped firstCmd = commands.get(0); assertEquals(iec61850ScheduleStart, firstCmd.getTimestamp().truncatedTo(SECONDS)); diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java index a82e6e4..bb13cc1 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleControllerNodeTests.java @@ -130,13 +130,13 @@ void activeControllerIsUpdated(ScheduleDefinitions scheduleConstants) //initial state: no schedule active -> reserve schedule is working //test, that ActSchdRef contains a reference of the reserve schedule - assertEquals(scheduleConstants.getReserveSchedule(), dut.readActiveSchedule(scheduleConstants.getController()), + assertEquals(scheduleConstants.getReserveSchedule(), dutAccess61850.readActiveSchedule(scheduleConstants.getController()), "Expecting reserve schedules to run in initial state"); String schedule = scheduleConstants.getScheduleName(1); //write and activate a schedule with a higher priority than the reserve schedule Instant scheduleStart = Instant.now().plus(Duration.ofSeconds(1)); - dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule), Duration.ofSeconds(2), scheduleStart, 100); while (Instant.now().isBefore(scheduleStart.plus(Duration.ofMillis(200)))) { @@ -144,13 +144,13 @@ void activeControllerIsUpdated(ScheduleDefinitions scheduleConstants) } //test, that ActSchdRef contains a reference of the active schedule - assertEquals(schedule, dut.readActiveSchedule(scheduleConstants.getController())); + assertEquals(schedule, dutAccess61850.readActiveSchedule(scheduleConstants.getController())); // wait until the active schedule finished service Thread.sleep(2000); //make sure the reserve schedule is active again - assertEquals(scheduleConstants.getReserveSchedule(), dut.readActiveSchedule(scheduleConstants.getController()), + assertEquals(scheduleConstants.getReserveSchedule(), dutAccess61850.readActiveSchedule(scheduleConstants.getController()), "Did not return to system reserve schedule after execution time"); } @@ -168,22 +168,22 @@ void activeControllerIsUpdatedWithScheduleOfHighestPrio(ScheduleDefinitions sche Instant start = Instant.now().plus(Duration.ofMillis(500)); // schedule 1 with low prio String schedule1Name = scheduleConstants.getScheduleName(1); - dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule1Name), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule1Name), Duration.ofSeconds(1), start, 20); // schedule 2 starts a bit after schedule 1 but with higher prio String schedule2Name = scheduleConstants.getScheduleName(2); - dut.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule2Name), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.getValueAccess().activateScheduleWithDefaultValue(schedule2Name), Duration.ofSeconds(1), start.plus(Duration.ofSeconds(1)), 200); // wait until start (and a bit longer), then schedule 1 should be active long millisUntilStart = Duration.between(Instant.now(), start).toMillis(); Thread.sleep(millisUntilStart + 200); - assertEquals(dut.readActiveSchedule(scheduleConstants.getController()), schedule1Name); + assertEquals(dutAccess61850.readActiveSchedule(scheduleConstants.getController()), schedule1Name); // sleep 1s, after that schedule 2 should be active Thread.sleep(1_000); - assertEquals(dut.readActiveSchedule(scheduleConstants.getController()), schedule2Name); + assertEquals(dutAccess61850.readActiveSchedule(scheduleConstants.getController()), schedule2Name); Thread.sleep(1000); } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java index 434a3cb..1b8e91e 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleExecutionTest.java @@ -51,12 +51,12 @@ public class ScheduleExecutionTest extends AllianderBaseTest { @BeforeAll public static void setDefaultValuesForReserveSchedules() throws ServiceError, IOException { - dut.writeScheduleValues( - dut.powerSchedules.getValueAccess().prepareWriting(0, dut.powerSchedules.getReserveSchedule())); - dut.writeScheduleValues( - dut.maxPowerSchedules.getValueAccess().prepareWriting(0, dut.maxPowerSchedules.getReserveSchedule())); - dut.writeScheduleValues( - dut.onOffSchedules.getValueAccess().prepareWriting(false, dut.onOffSchedules.getReserveSchedule())); + dutAccess61850.writeScheduleValues( + dutAccess61850.powerSchedules.getValueAccess().prepareWriting(0, dutAccess61850.powerSchedules.getReserveSchedule())); + dutAccess61850.writeScheduleValues( + dutAccess61850.maxPowerSchedules.getValueAccess().prepareWriting(0, dutAccess61850.maxPowerSchedules.getReserveSchedule())); + dutAccess61850.writeScheduleValues( + dutAccess61850.onOffSchedules.getValueAccess().prepareWriting(false, dutAccess61850.onOffSchedules.getReserveSchedule())); log.info("Set default values for reserve schedules"); } @@ -75,57 +75,57 @@ public void test_prioritiesPowerSchedules(ScheduleDefinitions scheduleCo final Instant schedulesStart = testExecutionStart.plus(ofSeconds(10)); //schedule 1: - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(10, 30, 70, 100, 100, 100), 1, interval, schedulesStart.plus(interval), 25)); // schedule 2: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(11, 31, 71, 99, 99, 99), 2, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(11, 31, 71, 99, 99, 99), 2, interval, schedulesStart.plus(interval.multipliedBy(5)), 40)); // schedule 3: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(12, 32, 72, 98, 98), 3, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(12, 32, 72, 98, 98), 3, interval, schedulesStart.plus(interval.multipliedBy(9)), 60)); //schedule 4, ends after 44s: - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(13, 33, 73, 97, 97, 97, 97, 97, 97, 97), 4, interval, schedulesStart.plus(interval.multipliedBy(13)), 70)); //schedule 5, ends after 42s - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70, 70, 70, 70), 5, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70, 70, 70, 70), 5, interval, schedulesStart.plus(interval.multipliedBy(17)), 100)); //schedule 6, - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 6, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 6, interval, schedulesStart.plus(interval.multipliedBy(18)), 120)); //schedule 7, - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 7, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(90), 7, interval, schedulesStart.plus(interval.multipliedBy(20)), 120)); //schedule 8: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(10), 8, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(10), 8, interval, schedulesStart.plus(interval.multipliedBy(22)), 80)); //schedule 9 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(80), 9, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(80), 9, interval, schedulesStart.plus(interval.multipliedBy(23)), 20)); //schedule 10 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 10, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 10, interval, schedulesStart.plus(interval.multipliedBy(24)), 11)); log.debug("Test setup took {}", Duration.between(testExecutionStart, now())); - float sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + float sysResValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()).floatValue(); List expectedValues = Arrays.asList(sysResValue, 10f, 30f, 70f, 100f, 11f, 31f, 71f, 99f, 12f, 32f, 72f, 98f, 13f, 33f, 73f, 97f, 70f, 90f, 70f, 90f, 70f, 10f, 80f, 100f, sysResValue); - List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(26), + List actualValues = dutAccess61850.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(26), interval, scheduleConstants); log.info("expected values {}", expectedValues); @@ -147,7 +147,7 @@ public void test_prioritiesOnOffSchedules(ScheduleDefinitions scheduleC final Instant testExecutionStart = now(); final Instant schedulesStart = testExecutionStart.plus(ofSeconds(5)); - boolean sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + boolean sysResValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); log.debug("Test setup took {}", Duration.between(testExecutionStart, now())); @@ -166,39 +166,39 @@ public void test_prioritiesOnOffSchedules(ScheduleDefinitions scheduleC // setting up schedules with increasing priorities, starting one after the other. exception: schedule 10 (is set up last) //schedule 1: - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(s1, s1, s1), 1, interval, schedulesStart.plus(interval), 15)); //schedule 2: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s2, s2, s2), 2, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s2, s2, s2), 2, interval, schedulesStart.plus(interval.multipliedBy(2)), 20)); //schedule 3: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s3, s3), 3, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s3, s3), 3, interval, schedulesStart.plus(interval.multipliedBy(3)), 30)); //schedule 4: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s4, s4), 4, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s4, s4), 4, interval, schedulesStart.plus(interval.multipliedBy(4)), 40)); //schedule 5: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s5, s5), 5, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s5, s5), 5, interval, schedulesStart.plus(interval.multipliedBy(5)), 50)); //schedule 6: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s6, s6), 6, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s6, s6), 6, interval, schedulesStart.plus(interval.multipliedBy(6)), 60)); //schedule 7: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s7, s7), 7, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s7, s7), 7, interval, schedulesStart.plus(interval.multipliedBy(7)), 70)); //schedule 8: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s8, s8), 8, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s8, s8), 8, interval, schedulesStart.plus(interval.multipliedBy(8)), 80)); //schedule 9: - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s9), 9, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s9), 9, interval, schedulesStart.plus(interval.multipliedBy(9)), 90)); //schedule 10: starts together with schedule 9 but with lower priority. lasts longer, so is activated after schedule 9 is stopped - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s10, s10), 10, interval, + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(s10, s10), 10, interval, schedulesStart.plus(interval.multipliedBy(9)), 11)); List expectedValues = Arrays.asList(sysResValue, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, sysResValue); - List actualValues = dut.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(12), + List actualValues = dutAccess61850.monitor(schedulesStart.plus(interval.dividedBy(2)), interval.multipliedBy(12), interval, scheduleConstants); log.info("expected values {}", expectedValues); @@ -224,25 +224,25 @@ public void testSamePriosDifferentStartPowerSchedules(ScheduleDefinitions schedu final Instant schedulesStart = testExecutionStart.plus(ofSeconds(4)); //schedule 5, start after 2s, duration 12s, Prio 40 - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(10, 10, 10, 10, 10, 10), 5, ofSeconds(4), schedulesStart, 40)); //schedule 1, start after 4s, duration 4s, Prio 40 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 100), 1, ofSeconds(4), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 100), 1, ofSeconds(4), schedulesStart.plus(ofSeconds(4)), 40)); //schedule 2, start after 8s, duration 4s, Prio 40 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70), 2, ofSeconds(4), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(70, 70), 2, ofSeconds(4), schedulesStart.plus(ofSeconds(12)), 40)); //schedule 3, start after 14s, duration 2s, Prio 60 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 3, ofSeconds(4), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(100), 3, ofSeconds(4), schedulesStart.plus(ofSeconds(24)), 60)); - float sysResValue = (float) dut.readConstantValueFromSysResScheduleFromModelNode( + float sysResValue = (float) dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); List expectedValues = Arrays.asList(sysResValue, 10f, 70f, 100f, 70f, 70f, 10f, 100f, sysResValue); Instant monitoringStart = testExecutionStart.plus(ofSeconds(2)); - List actualValues = dut.monitor(monitoringStart, ofSeconds(36), ofSeconds(4), scheduleConstants); + List actualValues = dutAccess61850.monitor(monitoringStart, ofSeconds(36), ofSeconds(4), scheduleConstants); log.info("expected values {}", expectedValues); log.info("observed values {}", actualValues); assertValuesMatch(expectedValues, actualValues, 0.01); @@ -263,19 +263,19 @@ public void testSamePriosDifferentStartOnOffSchedule(ScheduleDefinitions schedul final Instant schedulesStart = testExecutionStart.plus(ofSeconds(2)); //schedule 1, start after 2s, duration 6s, Prio 40 - dut.writeAndEnableSchedule( + dutAccess61850.writeAndEnableSchedule( scheduleConstants.prepareSchedule(Arrays.asList(true, true, true), 1, ofSeconds(2), schedulesStart, 40)); //schedule 2, start after 4s, duration 4s, Prio 40 - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(false, false), 2, ofSeconds(2), + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule(Arrays.asList(false, false), 2, ofSeconds(2), schedulesStart.plus(ofSeconds(2)), 40)); - boolean sysResValue = (boolean) dut.readConstantValueFromSysResScheduleFromModelNode( + boolean sysResValue = (boolean) dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); List expectedValues = Arrays.asList(sysResValue, true, false, false, sysResValue); Instant monitoringStart = testExecutionStart.plus(ofSeconds(1)); - List actualValues = dut.monitor(monitoringStart, ofSeconds(10), ofSeconds(2), scheduleConstants); + List actualValues = dutAccess61850.monitor(monitoringStart, ofSeconds(10), ofSeconds(2), scheduleConstants); log.info("expected values {}", expectedValues); log.info("observed values {}", actualValues); assertValuesMatch(expectedValues, actualValues); @@ -294,7 +294,7 @@ public void testSamePriosDifferentStartOnOffSchedule(ScheduleDefinitions schedul public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, IEC61850MissconfiguredException, InterruptedException { - float sysResValue = (float) dut.readConstantValueFromSysResScheduleFromModelNode( + float sysResValue = (float) dutAccess61850.readConstantValueFromSysResScheduleFromModelNode( scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); Instant start = Instant.now(); @@ -303,11 +303,11 @@ public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions sched PreparedSchedule schedule2 = scheduleConstants.prepareSchedule(Arrays.asList(100f, 100f, 100f), 2, ofSeconds(3), start.plus(ofSeconds(3)), 40); - dut.writeAndEnableSchedule(schedule1); - dut.writeAndEnableSchedule(schedule2); + dutAccess61850.writeAndEnableSchedule(schedule1); + dutAccess61850.writeAndEnableSchedule(schedule2); List expectedValues = Arrays.asList(sysResValue, 70f, 70f, 100f, sysResValue); - List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), + List actualValues = dutAccess61850.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), scheduleConstants); assertValuesMatch(expectedValues, actualValues, 0.01); } @@ -323,7 +323,7 @@ public void test_samePrioAndStartFloatSchedule(ScheduleDefinitions sched @MethodSource("getOnOffSchedules") public void test_samePrioAndStartOnOffSchedule(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, IEC61850MissconfiguredException, InterruptedException { - boolean sysResValue = dut.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), + boolean sysResValue = dutAccess61850.readConstantValueFromSysResScheduleFromModelNode(scheduleConstants.getValueAccess(), scheduleConstants.getReserveSchedule()); Instant start = Instant.now(); @@ -332,11 +332,11 @@ public void test_samePrioAndStartOnOffSchedule(ScheduleDefinitions sche PreparedSchedule schedule2 = scheduleConstants.prepareSchedule(Arrays.asList(false, false, false), 2, ofSeconds(3), start.plus(ofSeconds(3)), 40); - dut.writeAndEnableSchedule(schedule1); - dut.writeAndEnableSchedule(schedule2); + dutAccess61850.writeAndEnableSchedule(schedule1); + dutAccess61850.writeAndEnableSchedule(schedule2); List expectedValues = Arrays.asList(sysResValue, true, true, false, sysResValue); - List actualValues = dut.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), + List actualValues = dutAccess61850.monitor(start.plus(ofMillis(1000)), ofSeconds(15), ofSeconds(3), scheduleConstants); assertValuesMatch(expectedValues, actualValues); } diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java index ba49117..46d8641 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/ScheduleNodeTests.java @@ -169,19 +169,19 @@ void SchdEntrIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefiniti for (String scheduleName : scheduleConstants.getAllScheduleNames()) { //disable the schedule and display the name - dut.disableSchedule(scheduleName); + dutAccess61850.disableSchedule(scheduleName); log.info(scheduleName); //check if optional SchEntr is present - boolean isPresent = dut.nodeExists(scheduleName + ".SchdEntr"); + boolean isPresent = dutAccess61850.nodeExists(scheduleName + ".SchdEntr"); if (isPresent) { //display the state of the schedule - log.info("State of the schedule: " + dut.getScheduleState(scheduleName).toString()); + log.info("State of the schedule: " + dutAccess61850.getScheduleState(scheduleName).toString()); //if state of the schedule is not RUNNING SchdEntr might be 0 - if (dut.getScheduleState(scheduleName) != ScheduleState.RUNNING) { - String notRunningSchdEntrValueAsString = dut.getNodeEntryasString(scheduleName, "SchdEntr", + if (dutAccess61850.getScheduleState(scheduleName) != ScheduleState.RUNNING) { + String notRunningSchdEntrValueAsString = dutAccess61850.getNodeEntryasString(scheduleName, "SchdEntr", "stVal"); Assertions.assertEquals("0", notRunningSchdEntrValueAsString, "SchdEntry is not 0 although schedule is not running"); @@ -191,9 +191,9 @@ void SchdEntrIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefiniti PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(8), Instant.now().plusMillis(500), 20); - dut.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); Thread.sleep(4000); - String runningSchdEntrValueAsString = dut.getNodeEntryasString(scheduleName, "SchdEntr", "stVal"); + String runningSchdEntrValueAsString = dutAccess61850.getNodeEntryasString(scheduleName, "SchdEntr", "stVal"); Assertions.assertNotEquals("0", runningSchdEntrValueAsString, "SchdEntry is 0 although schedule is running"); } @@ -239,9 +239,9 @@ void ValSpsOrValMvIsUpdatedWithCurrentlyRunningSchedule(ScheduleDefinitions< anyPriorityHigherThanReserveSchedules); // initialize: enable schedule, then disable it again - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(1500); - dut.disableSchedules(scheduleName); + dutAccess61850.disableSchedules(scheduleName); final String spsValue = "ValSPS"; final String mvValue = "ValMV"; @@ -258,17 +258,17 @@ void ValSpsOrValMvIsUpdatedWithCurrentlyRunningSchedule(ScheduleDefinitions< shouldNotExist = spsValue; } - assertTrue(dut.nodeExists(scheduleName + "." + shouldExist)); + assertTrue(dutAccess61850.nodeExists(scheduleName + "." + shouldExist)); testOptionalNodeNotPresent(scheduleConstants, shouldNotExist); - Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, shouldExist, "q")); + Assertions.assertEquals("INVALID", dutAccess61850.getNodeEntryasString(scheduleName, shouldExist, "q")); final Instant startSecondSchedule = Instant.now().plus(interval).truncatedTo(ChronoUnit.SECONDS); final Instant startMonitoring = startSecondSchedule.plus(interval.dividedBy(2)); final PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), interval, startSecondSchedule, anyPriorityHigherThanReserveSchedules); - dut.writeAndEnableSchedule(preparedSchedule); - List actualValues = dut.monitor(startMonitoring, interval, interval, scheduleConstants); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); + List actualValues = dutAccess61850.monitor(startMonitoring, interval, interval, scheduleConstants); assertUntypedValuesMatch(expectedValues, actualValues); @@ -298,28 +298,28 @@ void ValEnsIsUpdatedWithCurrentlyRunningScheduleIfPresent(ScheduleDefinitions void ActStrTmIsUpdatedProperly(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, InterruptedException { for (String scheduleName : scheduleConstants.getAllScheduleNames()) { - if (dut.nodeExists(scheduleName + ".ActStrTm")) { + if (dutAccess61850.nodeExists(scheduleName + ".ActStrTm")) { PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(2), Instant.now().plusMillis(500), 20); //initial status - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(1500); - dut.disableSchedules(scheduleName); + dutAccess61850.disableSchedules(scheduleName); //if schedule is disabled, quality of ActStrTm should be invalid - Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, "ActStrTm", "q")); + Assertions.assertEquals("INVALID", dutAccess61850.getNodeEntryasString(scheduleName, "ActStrTm", "q")); //if schedule is active, ActStrTm.stVal should have the timestamp the active schedule started Instant timestamp = Instant.now().plusSeconds(2).truncatedTo(ChronoUnit.SECONDS); PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule( scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(4), timestamp, 20); - dut.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); Thread.sleep(3000); Assertions.assertEquals(timestamp.toString(), - dut.getNodeEntryasString(scheduleName, "ActStrTm", "stVal")); + dutAccess61850.getNodeEntryasString(scheduleName, "ActStrTm", "stVal")); } } } @@ -333,20 +333,20 @@ void NxtStrTmIsUpdatedProperly(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException, InterruptedException { for (String scheduleName : scheduleConstants.getAllScheduleNames()) { // disable the schedule such that there is no planned execution - dut.disableSchedules(scheduleName); + dutAccess61850.disableSchedules(scheduleName); // no planned execution -> NxtStrTm quality should be "INVALID" - Assertions.assertEquals("INVALID", dut.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); + Assertions.assertEquals("INVALID", dutAccess61850.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); // create a schedule in future such that we have a planned execution Instant timestamp = Instant.now().plusSeconds(10).truncatedTo(ChronoUnit.SECONDS); PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(2), timestamp, 200); - dut.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); //if schedule is active, ActStrTm.stVal should have the timestamp the active schedule started and NxtStrTm quality should be "GOOD" - Assertions.assertEquals(timestamp.toString(), dut.getNodeEntryasString(scheduleName, "NxtStrTm", "stVal")); - Assertions.assertEquals("GOOD", dut.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); + Assertions.assertEquals(timestamp.toString(), dutAccess61850.getNodeEntryasString(scheduleName, "NxtStrTm", "stVal")); + Assertions.assertEquals("GOOD", dutAccess61850.getNodeEntryasString(scheduleName, "NxtStrTm", "q")); } } @@ -364,22 +364,22 @@ void EnaReq_operating(ScheduleDefinitions scheduleConstants) PreparedSchedule preparedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(100), 100); - dut.writeAndEnableSchedule(preparedSchedule); - dut.disableSchedule(scheduleName); + dutAccess61850.writeAndEnableSchedule(preparedSchedule); + dutAccess61850.disableSchedule(scheduleName); Thread.sleep(2000); // test if intial state is correct: should be in inital state - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test 1: operating with value false should be possible the status should ignore that - BasicDataAttribute enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "false"); - dut.operate((FcModelNode) enableOp.getParent().getParent()); + BasicDataAttribute enableOp = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "false"); + dutAccess61850.operate((FcModelNode) enableOp.getParent().getParent()); // still same state: - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test2: when operating with value true on .EnaReq.Oper.ctlVal and when integrity check passes, schedule should be in ready state - enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) enableOp.getParent().getParent()); - Assertions.assertEquals(ScheduleState.READY, dut.getScheduleState(scheduleName)); + enableOp = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) enableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.READY, dutAccess61850.getScheduleState(scheduleName)); } } @@ -396,30 +396,30 @@ void DsaReq_operating(ScheduleDefinitions scheduleConstants) // intial: schedule has valid values set PreparedSchedule initialSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(initialSchedule); - dut.disableSchedule(scheduleName); + dutAccess61850.writeAndEnableSchedule(initialSchedule); + dutAccess61850.disableSchedule(scheduleName); Thread.sleep(2000); // test if initial state is correct: should be in NOT_READY - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test if operating with value false on DsaReq is ignored - BasicDataAttribute disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + BasicDataAttribute disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test, if in disabled state and operating DsaReq with true, state ist still NOT_READY - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); // test, if in enabled state and operating DsaReq with true, state turns into NOT_READY PreparedSchedule updatedSchedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(5), Instant.now().plusSeconds(1), 100); - dut.writeAndEnableSchedule(updatedSchedule); - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); + dutAccess61850.writeAndEnableSchedule(updatedSchedule); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); Thread.sleep(2000); - Assertions.assertEquals(ScheduleState.NOT_READY, dut.getScheduleState(scheduleName)); + Assertions.assertEquals(ScheduleState.NOT_READY, dutAccess61850.getScheduleState(scheduleName)); } } @@ -435,23 +435,23 @@ void schdEnaErr_HoldsMISSING_VALID_NUMENTRcorrectly(ScheduleDefinitions s // intial: valid values in NumEntr, Schdintv, SchdValues and test that SchdEnaErr shows no error kind PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(200); - Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dut.getSchdEnaErr(scheduleName)); - dut.disableSchedule(scheduleName); + Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dutAccess61850.getSchdEnaErr(scheduleName)); + dutAccess61850.disableSchedule(scheduleName); // provoke error MISSING_VALID_NUMENTR by setting NumEntr = -1 - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); - BasicDataAttribute disableOp1 = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); + BasicDataAttribute disableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp1 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + BasicDataAttribute enableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); // operating will throw, we ignore that error - dut.operate((FcModelNode) disableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) disableOp1.getParent().getParent()); Executable executable1 = () -> { - dut.operate((FcModelNode) enableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) enableOp1.getParent().getParent()); }; Assertions.assertThrows(ServiceError.class, executable1); - Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_NUMENTR, dut.getSchdEnaErr(scheduleName)); + Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_NUMENTR, dutAccess61850.getSchdEnaErr(scheduleName)); } } @@ -467,23 +467,23 @@ void SchdEnaErrHoldsMISSING_VALID_SCHDINTVcorrectly(ScheduleDefinitions s // intial: valid values in NumEntr, Schdintv, SchdValues and test that SchdEnaErr shows no error kind PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(200); - Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dut.getSchdEnaErr(scheduleName)); - dut.disableSchedule(scheduleName); + Assertions.assertEquals(ScheduleEnablingErrorKind.NONE, dutAccess61850.getSchdEnaErr(scheduleName)); + dutAccess61850.disableSchedule(scheduleName); // provoke error MISSING_VALID_SCHDINTV by setting SchdIntv = -1 - dut.setDataValues(scheduleName + ".SchdIntv.setVal", null, "-1"); - BasicDataAttribute disableOp1 = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, + dutAccess61850.setDataValues(scheduleName + ".SchdIntv.setVal", null, "-1"); + BasicDataAttribute disableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp1 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + BasicDataAttribute enableOp1 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); // operating will throw, we ignore that error - dut.operate((FcModelNode) disableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) disableOp1.getParent().getParent()); Executable executable1 = () -> { - dut.operate((FcModelNode) enableOp1.getParent().getParent()); + dutAccess61850.operate((FcModelNode) enableOp1.getParent().getParent()); }; Assertions.assertThrows(ServiceError.class, executable1); - Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHDINTV, dut.getSchdEnaErr(scheduleName)); + Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHDINTV, dutAccess61850.getSchdEnaErr(scheduleName)); } } @@ -504,20 +504,20 @@ void SchdEnaErrHoldsMISSING_VALID_SCHEDULE_VALUEScorrectly(ScheduleDefinitions { - dut.writeAndEnableSchedule(scheduleConstants.prepareSchedule( + dutAccess61850.writeAndEnableSchedule(scheduleConstants.prepareSchedule( Arrays.asList(Float.NaN, Float.MAX_VALUE, Float.POSITIVE_INFINITY), scheduleNumber, ofSeconds(2), Instant.now().plusSeconds(1), 100)); }; Assertions.assertThrows(ServiceError.class, excecutable); Assertions.assertEquals(ScheduleEnablingErrorKind.MISSING_VALID_SCHEDULE_VALUES, - dut.getSchdEnaErr(scheduleName)); + dutAccess61850.getSchdEnaErr(scheduleName)); } } @@ -535,32 +535,32 @@ void NumEntr_range(ScheduleDefinitions scheduleConstants) // intial: valid values in NumEntr PreparedSchedule schedule = scheduleConstants.prepareSchedule(scheduleConstants.getDefaultValues(1), scheduleConstants.getScheduleNumber(scheduleName), ofSeconds(1), Instant.now().plusSeconds(2), 100); - dut.writeAndEnableSchedule(schedule); + dutAccess61850.writeAndEnableSchedule(schedule); Thread.sleep(200); - dut.disableSchedule(scheduleName); + dutAccess61850.disableSchedule(scheduleName); //test: 0 can not bet set to NumEtr - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "0"); - BasicDataAttribute disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Executable executable = () -> dut.operate((FcModelNode) enableOp.getParent().getParent()); + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "0"); + BasicDataAttribute disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable = () -> dutAccess61850.operate((FcModelNode) enableOp.getParent().getParent()); Assertions.assertThrows(ServiceError.class, executable); //test: -1 can not bet set to NumEtr - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp2 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Executable executable2 = () -> dut.operate((FcModelNode) enableOp2.getParent().getParent()); + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "-1"); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp2 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable2 = () -> dutAccess61850.operate((FcModelNode) enableOp2.getParent().getParent()); Assertions.assertThrows(ServiceError.class, executable2); //test: 200 can not bet set to NumEtr - dut.setDataValues(scheduleName + ".NumEntr.setVal", null, "200"); - disableOp = dut.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); - BasicDataAttribute enableOp3 = dut.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); - dut.operate((FcModelNode) disableOp.getParent().getParent()); - Executable executable3 = () -> dut.operate((FcModelNode) enableOp3.getParent().getParent()); + dutAccess61850.setDataValues(scheduleName + ".NumEntr.setVal", null, "200"); + disableOp = dutAccess61850.findAndAssignValue(scheduleName + ".DsaReq.Oper.ctlVal", Fc.CO, "false"); + BasicDataAttribute enableOp3 = dutAccess61850.findAndAssignValue(scheduleName + ".EnaReq.Oper.ctlVal", Fc.CO, "true"); + dutAccess61850.operate((FcModelNode) disableOp.getParent().getParent()); + Executable executable3 = () -> dutAccess61850.operate((FcModelNode) enableOp3.getParent().getParent()); Assertions.assertThrows(ServiceError.class, executable3); } @@ -577,13 +577,13 @@ public void reserveSchedulesCannotBeDeactivated(ScheduleDefinitions scheduleCons // if all other schedules are deactivated, the reserve schedule should be running final String reserveSchedule = scheduleConstants.getReserveSchedule(); - Assertions.assertEquals(ScheduleState.RUNNING, dut.getScheduleState(reserveSchedule)); + Assertions.assertEquals(ScheduleState.RUNNING, dutAccess61850.getScheduleState(reserveSchedule)); try { - dut.disableSchedules(reserveSchedule); + dutAccess61850.disableSchedules(reserveSchedule); } catch (ServiceError e) { // an access violation may be thrown here, this indicates the schedule cannot be deactivated } - Assertions.assertEquals(ScheduleState.RUNNING, dut.getScheduleState(reserveSchedule)); + Assertions.assertEquals(ScheduleState.RUNNING, dutAccess61850.getScheduleState(reserveSchedule)); } @DisplayName("reserveSchedulesHaveFixedPriority") @@ -594,11 +594,11 @@ public void reserveSchedulesHaveFixedPriority(ScheduleDefinitions scheduleConsta throws ServiceError, IOException { final String reserveSchedule = scheduleConstants.getReserveSchedule(); try { - dut.setSchedulePrio(reserveSchedule, 100); + dutAccess61850.setSchedulePrio(reserveSchedule, 100); } catch (ServiceError e) { // an access violation may be thrown here, this indicates the prio cannot be changed } - Assertions.assertEquals(10, dut.readSchedulePrio(reserveSchedule)); + Assertions.assertEquals(10, dutAccess61850.readSchedulePrio(reserveSchedule)); } @DisplayName("reserveSchedulesHaveFixedStart") @@ -607,13 +607,13 @@ public void reserveSchedulesHaveFixedPriority(ScheduleDefinitions scheduleConsta @Requirements(S15) public void reserveSchedulesHaveFixedStart(ScheduleDefinitions scheduleConstants) throws ServiceError, IOException { final String reserveSchedule = scheduleConstants.getReserveSchedule(); - Assertions.assertEquals(Instant.ofEpochSecond(1), dut.getScheduleStart(reserveSchedule)); + Assertions.assertEquals(Instant.ofEpochSecond(1), dutAccess61850.getScheduleStart(reserveSchedule)); try { - dut.setScheduleStart(reserveSchedule, Instant.now()); + dutAccess61850.setScheduleStart(reserveSchedule, Instant.now()); } catch (ServiceError e) { // an access violation may be thrown here, this indicates the start date cannot be changed } - Assertions.assertEquals(Instant.ofEpochSecond(1), dut.getScheduleStart(reserveSchedule)); + Assertions.assertEquals(Instant.ofEpochSecond(1), dutAccess61850.getScheduleStart(reserveSchedule)); } /** @@ -626,7 +626,7 @@ public void reserveSchedulesHaveFixedStart(ScheduleDefinitions scheduleConstants */ private void testOptionalNodeNotPresent(ScheduleDefinitions scheduleConstants, String nodeName) { scheduleConstants.getAllScheduleNames().forEach(schedule -> { - org.junit.jupiter.api.Assertions.assertFalse(dut.nodeExists(schedule + "." + nodeName), + org.junit.jupiter.api.Assertions.assertFalse(dutAccess61850.nodeExists(schedule + "." + nodeName), "Optional node " + nodeName + " not relevant for this use case, so it should be left out (behavior cannot be tested)."); }); diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java index 35b2b7f..2a76ac2 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/UtilityTest.java @@ -15,6 +15,7 @@ import com.beanit.iec61850bean.ServiceError; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; import org.openmuc.fnn.steuerbox.models.AllianderDER; @@ -33,6 +34,7 @@ import static org.openmuc.fnn.steuerbox.AllianderTests.extractNumberFromLastNodeName; import static org.openmuc.fnn.steuerbox.mqtt.ParsingUtil.scheduleToJson; +@Tag("unit") public class UtilityTest { @Test From 256e460a0a4c510c45e728f802c62b818fd38489 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Fri, 26 Jul 2024 15:10:51 +0200 Subject: [PATCH 13/15] Fix command publishing test by running it first (bug for stability filed) Signed-off-by: Daniel Werner --- conformance-tests/00-run-single-test.sh | 4 - conformance-tests/01-reproduce-error.sh | 8 -- conformance-tests/reproduce-error.md | 17 --- .../fnn/steuerbox/EmsInterfacingTests.java | 128 ++++++++++-------- 4 files changed, 69 insertions(+), 88 deletions(-) delete mode 100755 conformance-tests/00-run-single-test.sh delete mode 100755 conformance-tests/01-reproduce-error.sh delete mode 100644 conformance-tests/reproduce-error.md diff --git a/conformance-tests/00-run-single-test.sh b/conformance-tests/00-run-single-test.sh deleted file mode 100755 index 1b46d5e..0000000 --- a/conformance-tests/00-run-single-test.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -echo "Test will only pass if it is run at first without as a single test." -./gradlew clean test --tests *EmsInterfacingTests.commandsAreForwardedJustOnTime diff --git a/conformance-tests/01-reproduce-error.sh b/conformance-tests/01-reproduce-error.sh deleted file mode 100755 index 5c13522..0000000 --- a/conformance-tests/01-reproduce-error.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -read -p "Please start fledge docker and hedera docker and press return" ignore_return_value - -echo "Running all EmsInterfacingTests. The default ordering of the test framework (junit) will cause the test 'commandsAreForwardedJustOnTime' to fail." - -./gradlew clean test --tests *EmsInterfacingTests* - diff --git a/conformance-tests/reproduce-error.md b/conformance-tests/reproduce-error.md deleted file mode 100644 index 86c5d2d..0000000 --- a/conformance-tests/reproduce-error.md +++ /dev/null @@ -1,17 +0,0 @@ -# Error description - -The fledge south plugin will stop publishing command messages (on topic "fledge/south-command"), the framework seems to work only partially as new schedules are published (on topic "fledge/south-schedule"). - -# How to reporoduce - -- delete all existing FLEDGE docker images -- recreate FLEDGE docker image -- start FLEDGE docker image -- start hedera docker image -- run 01-reproduce-error.sh ---> 5 tests will complete, 1 will fail: EmsInterfacingTests > commandsAreForwardedJustOnTime() - -# Additional scripts -The script 00-run-single-test.sh runs only the test "EmsInterfacingTests > commandsAreForwardedJustOnTime()", which will pass on fresh builds but fail if 01-reproduce-error.sh was run just before it. - -Stragely, the FLEDGE docker seems to recover after a certain time. If t00-run-single-test.sh is run ~30 min after 01-reproduce-error.sh, it passes again. diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java index 47b8e5e..862dbfb 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/EmsInterfacingTests.java @@ -4,7 +4,10 @@ import com.beanit.iec61850bean.ServiceError; import de.fhg.ise.testtool.utils.annotations.label.Description; import io.reactivex.Single; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.openmuc.fnn.steuerbox.mqtt.Command; import org.openmuc.fnn.steuerbox.mqtt.Schedule; import org.openmuc.fnn.steuerbox.scheduling.PreparedSchedule; @@ -33,6 +36,7 @@ *

* These tests are tailored and limited to max power schedules, in line with the default FLEDGE settings. */ +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class EmsInterfacingTests extends AllianderBaseTest { private static final Logger log = LoggerFactory.getLogger(EmsInterfacingTests.class); @@ -48,10 +52,72 @@ public EmsInterfacingTests() throws ExecutionException, InterruptedException, Se dutAccessMQTT = new MqttUtility(); } + @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, " + + "control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command." + + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on" + + " MQTT messages that are created by FLEDGE." + + "WARNING: this test only works if it is executed first, if the order is switched this is broken. This seems to be related to FLEDEGE. " + + "This behaviour is documented in https://github.com/alliander-opensource/ReLevENT/issues/20") + @Test + @Order(1) + void commandsAreForwardedJustOnTime() throws ServiceError, IOException, ExecutionException, InterruptedException { + + Instant iec61850ScheduleStart = Instant.now().plus(5, SECONDS).truncatedTo(SECONDS); + List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); + Duration iec61850ScheduleInterval = ofSeconds(1); + + // set up observation: watch all values from the schedule and changing back to default + final int commandUpdatesToObserve = iec61850ScheduleValues.size() + 1; + Single>> commandUpdates = dutAccessMQTT.fetchCommandUpdate( + commandUpdatesToObserve, iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) + .plus(Duration.between(Instant.now(), iec61850ScheduleStart).plus(ofSeconds(5)))); + // set up execution + PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// + iec61850ScheduleValues,// + 1,// fixed for the test: fledge setup tested and set up for this schedule + iec61850ScheduleInterval,// + iec61850ScheduleStart,// + 200);// schedule prio is arbitrary, needs to be something larger than default prio + dutAccess61850.writeAndEnableSchedule(iec61850schedule); + + // wait until command changes are observed + List> commands = commandUpdates.blockingGet(); + // do checks on 4 command updates: check values, publishing time of cmd and "sinceEpoch" of published payload + assertFalse(commands.isEmpty(), + "No MQTT commands where published localhost's MQTT broker @ topic " + dutAccessMQTT.CMD_TOPIC + "."); + assertEquals(4, commandUpdatesToObserve); + assertEquals(commandUpdatesToObserve, commands.size(), + "Expected exactly " + commandUpdatesToObserve + " MQTT command messages"); + + MqttUtility.Timestamped firstCmd = commands.get(0); + assertEquals(iec61850ScheduleStart, firstCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(iec61850ScheduleStart.getEpochSecond(), firstCmd.getObject().epochSecond); + assertEquals(1d, firstCmd.getObject().controlValue); + + MqttUtility.Timestamped secondCmd = commands.get(1); + Instant secondStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval); + assertEquals(secondStart, secondCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(secondStart.getEpochSecond(), secondCmd.getObject().epochSecond); + assertEquals(42d, secondCmd.getObject().controlValue); + + MqttUtility.Timestamped thirdCmd = commands.get(2); + Instant thirdStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(2)); + assertEquals(thirdStart, thirdCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(thirdStart.getEpochSecond(), thirdCmd.getObject().epochSecond); + assertEquals(1337d, thirdCmd.getObject().controlValue); + + MqttUtility.Timestamped fourthCmd = commands.get(3); + Instant fourthStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(3)); + assertEquals(fourthStart, fourthCmd.getTimestamp().truncatedTo(SECONDS)); + assertEquals(fourthStart.getEpochSecond(), fourthCmd.getObject().epochSecond); + assertEquals(defaultScheduleValue, commands.get(3).getObject().controlValue); + } + @Description("Tests that a schedule transmitted via MQTT will be forwarded to the IEC 61850 server. " + "Makes sure that schedule values and interval are maintained. Schedule priority is fixed to 20. " + "For the test setup, a schedule is created using a MQTT interface, the actual tests are carried out using a IEC 61850 client.") @Test + @Order(2) void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, InterruptedException { final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); final int scheduleNumber = 1; @@ -95,6 +161,7 @@ void schedulesAreForwardedAsIEC61850() throws ServiceError, IOException, Interru @Description("Tests that a schedule that covers an entire day can be created and transmitted via MQTT interface." + "For the test setup, a schedule is written using MQTT. The actual tests are carried out using a IEC 61850 client.") @Test + @Order(3) void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException { final Instant expectedStart = Instant.now().plus(Duration.ofMinutes(5)).truncatedTo(SECONDS); @@ -145,6 +212,7 @@ void oneDayCanBeCovered() throws ServiceError, IOException, InterruptedException + "Does not check 'FractionOfSecond' of published schedule." + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test + @Order(4) void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); @@ -190,6 +258,7 @@ void schedulesAreForwardedInExpectedFormat() throws ServiceError, IOException, I "Schedules are published via MQTT. Publishing interval is 5 seconds. Schedule values and schedule timestamps have the expected values which do not change over time. Does not check 'FractionOfSecond' of published schedule." + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on MQTT messages that are created by FLEDGE") @Test + @Order(5) void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, IOException, InterruptedException { Instant iec61850ScheduleStart = Instant.now().plus(3, HOURS).truncatedTo(SECONDS); @@ -241,63 +310,4 @@ void schedulesArePublishedEvery5Seconds_valuesDoNotDiffer() throws ServiceError, sched.getScheduleEntries().get(4).startEpochSecond); } } - - // TODO: test fails, command publishing works only upon first startup as it seems (MZ: why is that?) - @Description("Tests that a schedules values are forwarded as a command just in time. Check publishing time, " - + "control value and 'SecondsSinceEpoch' payload. Does not check 'FractionOfSecond' of published command." - + "For the test setup, a schedule is created using a IEC 61850 client. Then, the tests are carried out on" - + " MQTT messages that are created by FLEDGE") - @Test - void commandsAreForwardedJustOnTime() throws ServiceError, IOException, ExecutionException, InterruptedException { - - Instant iec61850ScheduleStart = Instant.now().plus(5, SECONDS).truncatedTo(SECONDS); - List iec61850ScheduleValues = Arrays.asList(1d, 42d, 1337d); - Duration iec61850ScheduleInterval = ofSeconds(1); - - // set up observation: watch all values from the schedule and changing back to default - final int commandUpdatesToObserve = iec61850ScheduleValues.size() + 1; - Single>> commandUpdates = dutAccessMQTT.fetchCommandUpdate( - commandUpdatesToObserve, iec61850ScheduleInterval.multipliedBy(commandUpdatesToObserve) - .plus(Duration.between(Instant.now(), iec61850ScheduleStart).plus(ofSeconds(5)))); - // set up execution - PreparedSchedule iec61850schedule = dutAccess61850.maxPowerSchedules.prepareSchedule(// - iec61850ScheduleValues,// - 1,// fixed for the test: fledge setup tested and set up for this schedule - iec61850ScheduleInterval,// - iec61850ScheduleStart,// - 200);// schedule prio is arbitrary, needs to be something larger than default prio - dutAccess61850.writeAndEnableSchedule(iec61850schedule); - - // wait until command changes are observed - List> commands = commandUpdates.blockingGet(); - // do checks on 4 command updates: check values, publishing time of cmd and "sinceEpoch" of published payload - assertFalse(commands.isEmpty(), - "No MQTT commands where published localhost's MQTT broker @ topic " + dutAccessMQTT.CMD_TOPIC + "."); - assertEquals(4, commandUpdatesToObserve); - assertEquals(commandUpdatesToObserve, commands.size(), - "Expected exactly " + commandUpdatesToObserve + " MQTT command messages"); - - MqttUtility.Timestamped firstCmd = commands.get(0); - assertEquals(iec61850ScheduleStart, firstCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(iec61850ScheduleStart.getEpochSecond(), firstCmd.getObject().epochSecond); - assertEquals(1d, firstCmd.getObject().controlValue); - - MqttUtility.Timestamped secondCmd = commands.get(1); - Instant secondStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval); - assertEquals(secondStart, secondCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(secondStart.getEpochSecond(), secondCmd.getObject().epochSecond); - assertEquals(42d, secondCmd.getObject().controlValue); - - MqttUtility.Timestamped thirdCmd = commands.get(2); - Instant thirdStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(2)); - assertEquals(thirdStart, thirdCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(thirdStart.getEpochSecond(), thirdCmd.getObject().epochSecond); - assertEquals(1337d, thirdCmd.getObject().controlValue); - - MqttUtility.Timestamped fourthCmd = commands.get(3); - Instant fourthStart = iec61850ScheduleStart.plus(iec61850ScheduleInterval.multipliedBy(3)); - assertEquals(fourthStart, fourthCmd.getTimestamp().truncatedTo(SECONDS)); - assertEquals(fourthStart.getEpochSecond(), fourthCmd.getObject().epochSecond); - assertEquals(defaultScheduleValue, commands.get(3).getObject().controlValue); - } } From 33ec3807d7eecc80153ad4b27525fd08d9318b96 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 31 Jul 2024 15:50:20 +0200 Subject: [PATCH 14/15] Conformace tests: - await connecting to MQTT broker - sleep between tests to make tests more stable Signed-off-by: Daniel Werner --- .../openmuc/fnn/steuerbox/testutils/MqttUtility.java | 11 ++--------- .../org/openmuc/fnn/steuerbox/AllianderBaseTest.java | 3 ++- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java index 6657c1d..28307cf 100644 --- a/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java +++ b/conformance-tests/src/main/java/org/openmuc/fnn/steuerbox/testutils/MqttUtility.java @@ -50,16 +50,9 @@ public MqttUtility() throws ExecutionException, InterruptedException { .serverPort(1883) .build(); - client.toAsync().connectWith().simpleAuth().username("") // no user required in local container + client.toBlocking().connectWith().simpleAuth().username("") // no user required in local container .password("".getBytes(StandardCharsets.UTF_8)) // no password required - .applySimpleAuth().send().orTimeout(100, TimeUnit.MILLISECONDS).whenComplete((ack, throwable) -> { - if (throwable != null) { - log.warn("Unable to connect. Is the mqtt docker container running?", throwable); - } - else { - log.debug("Connected successfully"); - } - }); + .applySimpleAuth().send(); subscribeTopic(CMD_TOPIC, () -> this.commandConsumer); subscribeTopic(SCHEDULE_TOPIC, () -> this.scheduleConsumer); diff --git a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java index e41f198..eb5c2eb 100644 --- a/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java +++ b/conformance-tests/src/test/java/org/openmuc/fnn/steuerbox/AllianderBaseTest.java @@ -53,9 +53,10 @@ public static void connectToDUT() throws ServiceError, IOException { } @BeforeEach - public void stopAllRunningSchedules() { + public void stopAllRunningSchedules() throws InterruptedException { disableAllRunningSchedules(); logger.debug("Disabled all schedules during init"); + Thread.sleep(500); } @AfterAll From ee230127a4dea4332d2c64671ada70dad4eabdcf Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Wed, 31 Jul 2024 16:02:30 +0200 Subject: [PATCH 15/15] Add prelimary unit test result including failed tests Signed-off-by: Daniel Werner --- ...eLevENT_IEC_61850_Conformance_Test_v0.9.pdf | Bin 0 -> 155105 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 conformance-tests/ReLevENT_IEC_61850_Conformance_Test_v0.9.pdf diff --git a/conformance-tests/ReLevENT_IEC_61850_Conformance_Test_v0.9.pdf b/conformance-tests/ReLevENT_IEC_61850_Conformance_Test_v0.9.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6bb7b13cb3218e2f04a620bd86a34e377fe7dc00 GIT binary patch literal 155105 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 avvl{ca`Qk!cQ_CPB#?RM%+b`>;{89j$icb* literal 0 HcmV?d00001