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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 50 additions & 5 deletions .github/workflows/TMS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,24 @@ jobs:
fetch-depth: 1
submodules: true

# Setup stacktrace
- name: install gdb
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install gdb
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
- name: change core file pattern
if: runner.os == 'Linux'
run: |
sudo sysctl -w kernel.core_pattern=core.%e.%p
echo Core file pattern set to:
cat /proc/sys/kernel/core_pattern

# Get 3rd-party Dependencies
- name: 'Install openssl, xerces (Linux)'
if: runner.os == 'Linux'
run: |-
sudo apt-get update
sudo apt-get -y install libssl-dev libxerces-c-dev
- name: 'Install xerces (macOS)'
if: runner.os == 'macOS'
Expand Down Expand Up @@ -226,7 +239,7 @@ jobs:
cd OpenDDS
. setenv.sh
cd ../tactical-microgrid-standard
cmake -B build_static
cmake -B build_static -D BUILD_TESTING=TRUE
cmake --build build_static
- name: 'Build TMS application with shared libs (Linux /macOS)'
if: runner.os == 'Linux' || runner.os == 'macOS'
Expand All @@ -235,7 +248,7 @@ jobs:
cd OpenDDS
. setenv.sh
cd ../tactical-microgrid-standard
cmake -DBUILD_SHARED_LIBS=yes -B build_shared
cmake -DBUILD_SHARED_LIBS=yes -B build_shared -D BUILD_TESTING=TRUE
cmake --build build_shared
- name: 'Build TMS application with static libs (Windows)'
if: runner.os == 'Windows'
Expand All @@ -244,7 +257,7 @@ jobs:
cd OpenDDS
call setenv.cmd
cd ..\tactical-microgrid-standard
cmake -B build_static
cmake -B build_static -D BUILD_TESTING=TRUE
cmake --build build_static
- name: 'Build TMS application with shared libs (Windows)'
if: runner.os == 'Windows'
Expand All @@ -253,5 +266,37 @@ jobs:
cd OpenDDS
call setenv.cmd
cd ..\tactical-microgrid-standard
cmake -DBUILD_SHARED_LIBS=yes -B build_shared
cmake -DBUILD_SHARED_LIBS=yes -B build_shared -D BUILD_TESTING=TRUE
cmake --build build_shared
- name: 'Run tests with static libs (Linux)'
if: runner.os == 'Linux'
run: |-
ulimit -c unlimited
cd OpenDDS
. setenv.sh
cd ../tactical-microgrid-standard/build_static
ctest --verbose --output-on-failure
- name: 'Run tests with shared libs (Linux)'
if: runner.os == 'Linux'
run: |-
ulimit -c unlimited
cd OpenDDS
. setenv.sh
cd ../tactical-microgrid-standard/build_shared
ctest --verbose --output-on-failure
- name: 'Run tests with static libs (Windows)'
if: runner.os == 'Windows'
shell: cmd
run: |-
cd OpenDDS
call setenv.cmd
cd ..\tactical-microgrid-standard\build_static
ctest --verbose --output-on-failure -C Debug
- name: 'Run tests with shared libs (Windows)'
if: runner.os == 'Windows'
shell: cmd
run: |-
cd OpenDDS
call setenv.cmd
cd ..\tactical-microgrid-standard\build_shared
ctest --verbose --output-on-failure -C Debug
20 changes: 8 additions & 12 deletions tactical-microgrid-standard/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ opendds_target_sources(TMS_Common
target_link_libraries(TMS_Common PUBLIC OpenDDS::Rtps_Udp)
target_compile_features(TMS_Common PUBLIC cxx_std_17)
opendds_bigobj(TMS_Common)
# Generated code with complete type objects enabled for the TMS IDL file
# causes stack overflow on Windows.
# Increase the stack size to 2MB (default is 1MB).
if (MSVC)
target_link_options(TMS_Common PUBLIC "/STACK:2097152")
endif()

add_library(Commands_Idl)
opendds_target_sources(Commands_Idl
Expand Down Expand Up @@ -87,16 +93,6 @@ add_executable(Distribution
target_include_directories(Distribution PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(Distribution PRIVATE PowerSim_Idl)

# Generated code with complete type objects enabled for the TMS IDL file
# causes stack overflow on Windows.
# Increase the stack size to 2MB (default is 1MB).
if (MSVC)
target_link_options(Controller PRIVATE "/STACK:2097152")
target_link_options(CLI PRIVATE "/STACK:2097152")
target_link_options(Source PRIVATE "/STACK:2097152")
target_link_options(Load PRIVATE "/STACK:2097152")
target_link_options(Distribution PRIVATE "/STACK:2097152")
if(BUILD_TESTING)
add_subdirectory(tests)
endif()


add_subdirectory(tests)
18 changes: 16 additions & 2 deletions tactical-microgrid-standard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ cmake --build <build_dir>
- `cli/`: Command-line interface implementation
- `cli_idl/`: Interface definition files for CLI commands
- `common/`: Shared libraries and utilities
- TMS data model definitions (mil-std-3071_data_model.idl)
- TMS data model definitions (`mil-std-3071_data_model.idl`)
- TMS Handshaking function
- TMS microgrid controller selection
- TMS QoS profiles
Expand All @@ -46,13 +46,27 @@ cmake --build <build_dir>

## Testing

Tests can be run using CTest after building the project:
Tests can be run using CTest after building the project with `-D BUILD_TESTING=TRUE`:

```bash
cd <build_dir>
ctest
```

## Configuration

These programs support the following OpenDDS configuration properties. There
are multiple ways to set these, see
[OpenDDS runtime configuration](https://opendds.readthedocs.io/en/master/devguide/run_time_configuration.html)
for more info.

- `TMS_SELECTOR_DEBUG=<boolean>`
- Enables debug logging of the microgrid controller selection process of power devices.
- Command line option example: `-OpenDDS-tms-selector-debug true`
- `TMS_CONTROLLER_DEBUG=<boolean>`
- Enables debug logging of what devices the controller has learned about.
- Command line option example: `-OpenDDS-tms-controller-debug true`

## References

- [Tactical Microgrid Standard (MIL-STD-3071)](https://quicksearch.dla.mil/qsDocDetails.aspx?ident_number=285095)
Expand Down
111 changes: 111 additions & 0 deletions tactical-microgrid-standard/common/Configurable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#ifndef TMS_COMMON_CONFIGURABLE
#define TMS_COMMON_CONFIGURABLE

#include <dds/DCPS/ConfigStoreImpl.h>
#include <dds/DCPS/InternalDataReaderListener.h>
#include <dds/DCPS/Service_Participant.h>

#include <mutex>

class Configurable {
public:
using Mutex = std::recursive_mutex;
using Guard = std::lock_guard<Mutex>;

Configurable(const std::string& prefix)
: config_prefix_(prefix)
{
}

virtual ~Configurable()
{
Guard g(config_lock_);

if (config_reader_) {
TheServiceParticipant->config_topic()->disconnect(config_reader_);
}
}

void setup_config()
{
Guard g(config_lock_);

if (!config_reader_) {
config_listener_ = OpenDDS::DCPS::make_rch<ConfigListener>(this, config_prefix_ + "_");
config_reader_ = OpenDDS::DCPS::make_rch<OpenDDS::DCPS::ConfigReader>(
TheServiceParticipant->config_store()->datareader_qos(), config_listener_);
TheServiceParticipant->config_topic()->connect(config_reader_);
}
}

const std::string& config_prefix() const
{
return config_prefix_;
}

static bool convert_bool(const OpenDDS::DCPS::ConfigPair& pair, bool& value)
{
DDS::Boolean x = 0;
if (pair.value() == "true") {
value = true;
return true;
} else if (pair.value() == "false") {
value = false;
return true;
} else if (OpenDDS::DCPS::convertToInteger(pair.value(), x)) {
value = x;
return true;
} else {
ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: Configurable::convert_bool: failed to parse boolean for %C=%C\n",
pair.key().c_str(), pair.value().c_str()));
return false;
}
}

virtual bool got_config(const std::string& name, const OpenDDS::DCPS::ConfigPair& pair) = 0;

private:
class ConfigListener : public OpenDDS::DCPS::ConfigListener {
public:
explicit ConfigListener(Configurable* configurable, const std::string& prefix)
: OpenDDS::DCPS::ConfigListener(TheServiceParticipant->job_queue())
, configurable_(*configurable)
, prefix_(prefix)
{
}

void on_data_available(InternalDataReader_rch reader) override
{
OpenDDS::DCPS::ConfigReader::SampleSequence samples;
OpenDDS::DCPS::InternalSampleInfoSequence infos;
reader->read(samples, infos, DDS::LENGTH_UNLIMITED,
DDS::NOT_READ_SAMPLE_STATE, DDS::ANY_VIEW_STATE, DDS::ANY_INSTANCE_STATE);
for (size_t idx = 0; idx != samples.size(); ++idx) {
const auto& info = infos[idx];
if (info.valid_data) {
const auto& pair = samples[idx];
// Match key to prefix and pass rest of key as a short name
if (pair.key().substr(0, prefix_.length()) == prefix_) {
const auto name = pair.key().substr(prefix_.length());
if (!configurable_.got_config(name, pair)) {
ACE_ERROR((LM_WARNING, "(%P|%t) WARNING: Configurable::ConfigListener::on_data_available: "
"%C is not a valid property for %C\n",
name.c_str(), configurable_.config_prefix().c_str()));
}
}
}
}
}

private:
Configurable& configurable_;
const std::string prefix_;
};

mutable Mutex config_lock_;
const std::string config_prefix_;
OpenDDS::DCPS::RcHandle<OpenDDS::DCPS::ConfigReader> config_reader_;
OpenDDS::DCPS::RcHandle<ConfigListener> config_listener_;
};

#endif
Loading