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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .github/workflows/control-termination-profile-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Control Termination Profile CI

on:
push:
branches:
- main
pull_request:
paths:
- 'include/ariec61850/control/**'
- 'src/control/**'
- 'tests/test_command_termination.cpp'
- 'tests/control_termination_profile/**'
- 'include/ariec61850/mms/data_value.hpp'
- 'include/ariec61850/mms/reporting.hpp'
- 'src/mms/data_value.cpp'
- '.github/workflows/control-termination-profile-ci.yml'

permissions:
contents: read

jobs:
control-termination-profile:
name: Control Termination / ${{ matrix.compiler }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
compiler: [gcc, clang]

steps:
- uses: actions/checkout@v4

- name: Select compiler
shell: bash
run: |
if [ "${{ matrix.compiler }}" = "clang" ]; then
echo "CC=clang" >> "$GITHUB_ENV"
echo "CXX=clang++" >> "$GITHUB_ENV"
else
echo "CC=gcc" >> "$GITHUB_ENV"
echo "CXX=g++" >> "$GITHUB_ENV"
fi

- name: Configure control termination profile
run: cmake -S tests/control_termination_profile -B build-control-termination

- name: Build control termination profile
run: cmake --build build-control-termination --parallel

- name: Run CommandTermination parity tests
run: >-
ctest --test-dir build-control-termination
--output-on-failure
--output-junit control-termination-ctest.xml

- name: Upload termination evidence
uses: actions/upload-artifact@v4
with:
name: control-termination-${{ matrix.compiler }}-${{ github.event.pull_request.head.sha || github.sha }}
if-no-files-found: error
retention-days: 14
path: build-control-termination/control-termination-ctest.xml
57 changes: 57 additions & 0 deletions include/ariec61850/control/command_termination.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once

#include "ariec61850/control/guarded_control.hpp"
#include "ariec61850/mms/reporting.hpp"

#include <cstdint>
#include <optional>
#include <string>

namespace ar::iec61850::control {

struct LastApplError final {
std::string control_object;
std::int64_t raw_control_error{};
std::int64_t raw_add_cause{25};
ControlError control_error{ControlError::no_error};
AddCause add_cause{AddCause::none};
std::string control_error_name;
std::string add_cause_name;
};

struct CommandTermination final {
bool is_for_control_object{};
bool is_termination{};
bool positive{};
ControlError control_error{ControlError::no_error};
AddCause add_cause{AddCause::none};
std::int64_t raw_control_error{};
std::int64_t raw_add_cause{25};
std::string control_error_name;
std::string add_cause_name;
std::optional<LastApplError> last_appl_error;
};

class CommandTerminationDecoder final {
public:
[[nodiscard]] static CommandTermination decode(
const mms::MmsInformationReport& report,
const ControlObjectReference& object);

[[nodiscard]] static std::optional<LastApplError> try_decode_last_appl_error(
const mms::MmsDataValue& value);

[[nodiscard]] static bool matches_operate_reference(
const ControlObjectReference& object,
const std::string& reference);

[[nodiscard]] static bool matches_reported_reference(
const ControlObjectReference& object,
const std::string& reference);

[[nodiscard]] static std::string control_error_name(std::int64_t value);
[[nodiscard]] static std::string add_cause_name(std::int64_t value);
};

} // namespace ar::iec61850::control
Loading
Loading