diff --git a/apps/ccam/ccam.cpp b/apps/ccam/ccam.cpp index b8d7a38..d1cff50 100644 --- a/apps/ccam/ccam.cpp +++ b/apps/ccam/ccam.cpp @@ -1,292 +1,293 @@ //===-- apps/ccam/ccam.cpp --------------------------------------*- C++ -*-===// // // The RoSA Framework -- Application CCAM // //===----------------------------------------------------------------------===// /// /// \file apps/ccam/ccam.cpp /// /// \author Maximilian Goetzinger (maximilian.goetzinger@tuwien.ac.at) /// \author Benedikt Tutzer (benedikt.tutzer@tuwien.ac.at) /// /// \date 2019 /// /// \brief The application CCAM implements the case study from the paper: /// M. Goetzinger, N. TaheriNejad, H. A. Kholerdi, A. Jantsch, E. Willegger, /// T. Glatzl, A.M. Rahmani, T.Sauter, P. Liljeberg: Model - Free Condition /// Monitoring with Confidence //===----------------------------------------------------------------------===// #include "rosa/agent/Abstraction.hpp" #include "rosa/agent/Confidence.hpp" #include "rosa/agent/FunctionAbstractions.hpp" #include #include "rosa/config/version.h" #include "rosa/agent/SignalStateDetector.hpp" #include "rosa/agent/SystemStateDetector.hpp" #include "rosa/deluxe/DeluxeContext.hpp" #include "rosa/support/csv/CSVReader.hpp" #include "rosa/support/csv/CSVWriter.hpp" #include #include #include #include #include "configuration.h" #include "statehandlerutils.h" using namespace rosa; using namespace rosa::agent; using namespace rosa::deluxe; using namespace rosa::terminal; const std::string AppName = "CCAM"; int main(int argc, char **argv) { LOG_INFO_STREAM << '\n' << library_string() << " -- " << Color::Red << AppName << "app" << Color::Default << '\n'; if (argc < 2) { LOG_ERROR("Specify config File!\nUsage:\n\tccam config.json"); return 1; } std::string ConfigPath = argv[1]; if (!readConfigFile(ConfigPath)) { LOG_ERROR_STREAM << "Could not read config from \"" << ConfigPath << "\"\n"; return 2; } std::string InputFilePath, OutputFilePath; LOG_INFO("Creating Context"); std::unique_ptr C = DeluxeContext::create(AppName); std::shared_ptr> BrokenDelayFunction( new PartialFunction( {{{0, AppConfig.BrokenCounter}, std::make_shared>( 0, 0.f, AppConfig.BrokenCounter, 1.f)}, {{AppConfig.BrokenCounter, std::numeric_limits::max()}, std::make_shared>(1.f, 0.f)}}, 0.f)); std::shared_ptr> OkDelayFunction( new PartialFunction( {{{0, AppConfig.BrokenCounter}, std::make_shared>( 0, 1.f, AppConfig.BrokenCounter, 0.f)}, {{AppConfig.BrokenCounter, std::numeric_limits::max()}, std::make_shared>(0.f, 0.f)}}, 1.f)); // // Create a DeluxeAgent with SystemStateDetector functionality. // LOG_INFO("Create SystemStateDetector agent."); AgentHandle SystemStateDetectorAgent = createSystemStateDetectorAgent( C, "SystemStateDetector", AppConfig.SignalConfigurations.size(), BrokenDelayFunction, OkDelayFunction); C->setExecutionPolicy(SystemStateDetectorAgent, DeluxeExecutionPolicy::awaitAll({})); LOG_INFO("Creating sensors, SignalStateDetector functionalities and their " "Abstractions."); std::vector Sensors; std::vector>> SampleMatchesFunctions; std::vector>> SampleMismatchesFunctions; std::vector>> SignalIsStableFunctions; std::vector>> SignalIsDriftingFunctions; std::vector>> NumOfSamplesMatchFunctions; std::vector>> NumOfSamplesMismatchFunctions; std::vector>> SignalStateDetectors; std::vector SignalStateDetectorAgents; + std::vector DataFiles; for (auto SignalConfiguration : AppConfig.SignalConfigurations) { // // Create deluxe sensors. // Sensors.emplace_back(C->createSensor(SignalConfiguration.Name)); // // Create functionalities for SignalStateDetector. // SampleMatchesFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 0.f, -SignalConfiguration.InnerBound, 1.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(1.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 1.f, SignalConfiguration.OuterBound, 0.f)}, }, 0)); SampleMismatchesFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBound, -SignalConfiguration.InnerBound}, std::make_shared>( -SignalConfiguration.OuterBound, 1.f, -SignalConfiguration.InnerBound, 0.f)}, {{-SignalConfiguration.InnerBound, SignalConfiguration.InnerBound}, std::make_shared>(0.f, 0.f)}, {{SignalConfiguration.InnerBound, SignalConfiguration.OuterBound}, std::make_shared>( SignalConfiguration.InnerBound, 0.f, SignalConfiguration.OuterBound, 1.f)}, }, 1)); SignalIsStableFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBoundDrift, -SignalConfiguration.InnerBoundDrift}, std::make_shared>( -SignalConfiguration.OuterBoundDrift, 0.f, -SignalConfiguration.InnerBoundDrift, 1.f)}, {{-SignalConfiguration.InnerBoundDrift, SignalConfiguration.InnerBoundDrift}, std::make_shared>(1.f, 0.f)}, {{SignalConfiguration.InnerBoundDrift, SignalConfiguration.OuterBoundDrift}, std::make_shared>( SignalConfiguration.InnerBoundDrift, 1.f, SignalConfiguration.OuterBoundDrift, 0.f)}, }, 0)); SignalIsDriftingFunctions.emplace_back(new PartialFunction( { {{-SignalConfiguration.OuterBoundDrift, -SignalConfiguration.InnerBoundDrift}, std::make_shared>( -SignalConfiguration.OuterBoundDrift, 1.f, -SignalConfiguration.InnerBoundDrift, 0.f)}, {{-SignalConfiguration.InnerBoundDrift, SignalConfiguration.InnerBoundDrift}, std::make_shared>(0.f, 0.f)}, {{SignalConfiguration.InnerBoundDrift, SignalConfiguration.OuterBoundDrift}, std::make_shared>( SignalConfiguration.InnerBoundDrift, 0.f, SignalConfiguration.OuterBoundDrift, 1.f)}, }, 1)); NumOfSamplesMatchFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepUp)); NumOfSamplesMismatchFunctions.emplace_back(new StepFunction( 1.0f / SignalConfiguration.SampleHistorySize, StepDirection::StepDown)); // // Create SignalStateDetector functionality // SignalStateDetectors.emplace_back( new SignalStateDetector( SignalConfiguration.Output ? SignalProperties::OUTPUT : SignalProperties::INPUT, std::numeric_limits::max(), SampleMatchesFunctions.back(), SampleMismatchesFunctions.back(), NumOfSamplesMatchFunctions.back(), NumOfSamplesMismatchFunctions.back(), SignalIsDriftingFunctions.back(), SignalIsStableFunctions.back(), SignalConfiguration.SampleHistorySize, SignalConfiguration.DABSize, SignalConfiguration.DABHistorySize)); // // Create low-level deluxe agents // SignalStateDetectorAgents.push_back(createSignalStateDetectorAgent( C, SignalConfiguration.Name, SignalStateDetectors.back())); - // - // Open CSV files and register them for their corresponding sensors. - // - std::ifstream SensorData(SignalConfiguration.InputPath); - if (!SensorData) { - LOG_ERROR_STREAM << "Cannot open Input File \"" - << SignalConfiguration.InputPath << "\" for Signal \"" - << SignalConfiguration.Name << "\"" << std::endl; - return 3; - } - - C->registerSensorValues(Sensors.back(), csv::CSVIterator(SensorData), - csv::CSVIterator()); - // // Connect sensors to low-level agents. // LOG_INFO("Connect sensors to their corresponding low-level agents."); C->connectSensor(SignalStateDetectorAgents.back(), 0, Sensors.back(), SignalConfiguration.Name); C->connectAgents(SystemStateDetectorAgent, SignalStateDetectors.size() - 1, SignalStateDetectorAgents.back(), SignalConfiguration.Name); } // // For simulation output, create a logger agent writing the output of the // high-level agent into a CSV file. // LOG_INFO("Create a logger agent."); // Create CSV writer. std::ofstream OutputCSV(AppConfig.OutputFilePath); // The agent writes each new input value into a CSV file and produces nothing. using Input = std::pair; using Result = Optional>; using Handler = std::function; std::string Name = "Logger Agent"; AgentHandle LoggerAgent = C->createAgent("Logger Agent", Handler([&OutputCSV](Input I) -> Result { OutputCSV << std::get<0>(I.first) << std::endl; return Result(); })); - C->setExecutionPolicy(LoggerAgent, DeluxeExecutionPolicy::awaitAny({})); // // Connect the high-level agent to the logger agent. // LOG_INFO("Connect the high-level agent to the logger agent."); C->connectAgents(LoggerAgent, 0, SystemStateDetectorAgent, "SystemStateDetector Channel"); // // Do simulation. // LOG_INFO("Setting up and performing simulation."); // // Initialize deluxe context for simulation. // C->initializeSimulation(); // - // Simulate. + // Open CSV files and register them for their corresponding sensors. // + for (auto SignalConfiguration : AppConfig.SignalConfigurations) { + DataFiles.emplace_back(SignalConfiguration.InputPath); + if (!DataFiles.back()) { + LOG_ERROR_STREAM << "Cannot open Input File \"" + << SignalConfiguration.InputPath << "\" for Signal \"" + << SignalConfiguration.Name << "\"" << std::endl; + return 3; + } + C->registerSensorValues(Sensors.back(), + csv::CSVIterator(DataFiles.back()), + csv::CSVIterator()); + } + // + // Simulate. + // C->simulate(AppConfig.NumberOfSimulationCycles); return 0; } diff --git a/apps/ccam/sample_data/.~lock.in1.csv# b/apps/ccam/sample_data/.~lock.in1.csv# deleted file mode 100644 index b94dc35..0000000 --- a/apps/ccam/sample_data/.~lock.in1.csv# +++ /dev/null @@ -1 +0,0 @@ -,benedikt,pc80-73.ICT.TUWIEN.AC.AT,11.07.2019 16:59,file:///home/benedikt/.config/libreoffice/4; \ No newline at end of file diff --git a/apps/ccam/sample_data/out.csv b/apps/ccam/sample_data/out.csv deleted file mode 100644 index e69de29..0000000 diff --git a/apps/ccam/sample_data/sample_config.json b/apps/ccam/sample_data/sample_config.json index bb2d3f9..6b16a45 100644 --- a/apps/ccam/sample_data/sample_config.json +++ b/apps/ccam/sample_data/sample_config.json @@ -1,20 +1,20 @@ { "OutputFilePath": "./out.csv", "BrokenCounter": 10, - "NumberOfSimulationCycles": 100, + "NumberOfSimulationCycles": 3, "SignalConfigurations": [ { "Name" : "Sig1", "InputPath" : "./in1.csv", "Output" : false, "InnerBound" : 0.1, "OuterBound" : 0.2, "InnerBoundDrift" : 0.3, "OuterBoundDrift" : 0.4, "SampleHistorySize" : 10, "DABSize" : 10, "DABHistorySize" : 5 } ] } diff --git a/include/rosa/agent/SystemState.hpp b/include/rosa/agent/SystemState.hpp index 34e52b7..14a3a25 100644 --- a/include/rosa/agent/SystemState.hpp +++ b/include/rosa/agent/SystemState.hpp @@ -1,283 +1,283 @@ //===-- rosa/agent/SystemState.hpp ------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file rosa/agent/SystemState.hpp /// /// \author Maximilian Götzinger (maximilian.goetzinger@tuwien.ac.at) /// /// \date 2019 /// /// \brief Definition of *system state* *functionality*. /// //===----------------------------------------------------------------------===// #ifndef ROSA_AGENT_SYSTEMSTATE_HPP #define ROSA_AGENT_SYSTEMSTATE_HPP #include "rosa/agent/Functionality.h" #include "rosa/agent/SignalState.hpp" #include "rosa/agent/State.hpp" #include "rosa/support/debug.hpp" #include namespace rosa { namespace agent { enum class SystemStateRelation : uint8_t { STATEISMATCHING = 0, ///< The system state is matching ONLYINPUTISMATCHING = 1, ///< Only inputs of the system state are matching ONLYOUTPUTISMATCHING = 2, ///< Only outputs of the system state are matching STATEISMISMATCHING = 3 ///< The system state is mismatching }; /// TODO: write description template struct SystemStateInformation : StateInformation { /// TODO: describe CONFDATATYPE ConfidenceOfInputsMatchingState; CONFDATATYPE ConfidenceOfInputsMismatchingState; CONFDATATYPE ConfidenceOfOutputsMatchingState; CONFDATATYPE ConfidenceOfOutputsMismatchingState; CONFDATATYPE ConfidenceSystemIsFunctioning; CONFDATATYPE ConfidenceSystemIsMalfunctioning; CONFDATATYPE ConfidenceOfAllDecisions; public: SystemStateInformation() {} SystemStateInformation(unsigned int _SystemStateID, StateConditions _StateCondition) { this->StateID = _SystemStateID; this->StateCondition = _StateCondition; this->StateIsValid = false; this->StateJustGotValid = false; this->StateIsValidAfterReentrance = false; this->ConfidenceOfInputsMatchingState = 0; this->ConfidenceOfInputsMismatchingState = 0; this->ConfidenceOfOutputsMatchingState = 0; this->ConfidenceOfOutputsMismatchingState = 0; this->ConfidenceSystemIsFunctioning = 0; this->ConfidenceSystemIsMalfunctioning = 0; this->ConfidenceOfAllDecisions = 0; } }; // todo: do we need PROCDATATYPE? /// TODO TEXT template class SystemState : public State { // Make sure the actual type arguments are matching our expectations. STATIC_ASSERT(std::is_arithmetic::value, "input data type is not to arithmetic"); STATIC_ASSERT(std::is_arithmetic::value, "confidence abstraction type is not to arithmetic"); STATIC_ASSERT(std::is_arithmetic::value, "process data type is not to arithmetic"); private: /// SignalStateInfo is a struct of SignalStateInformation that contains /// information about the current signal state. SystemStateInformation SystemStateInfo; std::vector> SignalStateInfos; uint32_t NumberOfSignals; public: /// TODO: write description SystemState(uint32_t StateID, uint32_t NumberOfSignals) noexcept : SystemStateInfo(StateID, StateConditions::UNKNOWN), NumberOfSignals(NumberOfSignals) { SignalStateInfos.resize(NumberOfSignals); } /// Destroys \p this object. ~SystemState(void) = default; /// TODO: write description SystemStateInformation insertSignalStateInformation( const std::vector> _SignalStateInfos) noexcept { - ASSERT(_SignalStateInfos.size() < NumberOfSignals); + ASSERT(_SignalStateInfos.size() == NumberOfSignals); bool AllSignalsAreValid = true; bool AtLeastOneSignalJustGotValid = false; bool AllSignalsAreValidAfterReentrance = true; bool AtLeastOneSignalIsUnknown = false; bool AllSignalsAreStable = true; // TODO: change this SystemStateInfo.ConfidenceOfInputsMatchingState = 1; SystemStateInfo.ConfidenceOfInputsMismatchingState = 0; SystemStateInfo.ConfidenceOfOutputsMatchingState = 1; SystemStateInfo.ConfidenceOfOutputsMismatchingState = 0; SystemStateInfo.ConfidenceStateIsValid = 1; SystemStateInfo.ConfidenceStateIsInvalid = 0; SystemStateInfo.ConfidenceStateIsStable = 1; SystemStateInfo.ConfidenceStateIsDrifting = 0; std::size_t counter = 0; for (auto SSI : _SignalStateInfos) { if (!SSI.StateIsValid) AllSignalsAreValid = false; if (SSI.StateJustGotValid) AtLeastOneSignalJustGotValid = true; if (!SSI.StateIsValidAfterReentrance) AllSignalsAreValidAfterReentrance = false; if (SSI.StateCondition == StateConditions::UNKNOWN) AtLeastOneSignalIsUnknown = true; if (SSI.StateCondition == StateConditions::DRIFTING) AllSignalsAreStable = false; if (SSI.SignalProperty == SignalProperties::INPUT) { SystemStateInfo.ConfidenceOfInputsMatchingState = fuzzyAND(SystemStateInfo.ConfidenceOfInputsMatchingState, SSI.ConfidenceOfMatchingState); SystemStateInfo.ConfidenceOfInputsMismatchingState = fuzzyOR(SystemStateInfo.ConfidenceOfInputsMismatchingState, SSI.ConfidenceOfMismatchingState); } else { SystemStateInfo.ConfidenceOfOutputsMatchingState = fuzzyAND(SystemStateInfo.ConfidenceOfOutputsMatchingState, SSI.ConfidenceOfMatchingState); SystemStateInfo.ConfidenceOfOutputsMismatchingState = fuzzyOR(SystemStateInfo.ConfidenceOfOutputsMismatchingState, SSI.ConfidenceOfMismatchingState); } SystemStateInfo.ConfidenceStateIsValid = fuzzyAND( SystemStateInfo.ConfidenceStateIsValid, SSI.ConfidenceStateIsValid); SystemStateInfo.ConfidenceStateIsInvalid = fuzzyOR(SystemStateInfo.ConfidenceStateIsInvalid, SSI.ConfidenceStateIsInvalid); SystemStateInfo.ConfidenceStateIsStable = fuzzyAND( SystemStateInfo.ConfidenceStateIsStable, SSI.ConfidenceStateIsStable); SystemStateInfo.ConfidenceStateIsDrifting = fuzzyOR(SystemStateInfo.ConfidenceStateIsDrifting, SSI.ConfidenceStateIsDrifting); this->SignalStateInfos.at(counter) = SSI; counter++; } SystemStateInfo.StateIsValid = AllSignalsAreValid; SystemStateInfo.StateJustGotValid = AllSignalsAreValid && AtLeastOneSignalJustGotValid; SystemStateInfo.StateIsValidAfterReentrance = AllSignalsAreValidAfterReentrance; if (AtLeastOneSignalIsUnknown) SystemStateInfo.StateCondition = StateConditions::UNKNOWN; else if (AllSignalsAreStable) SystemStateInfo.StateCondition = StateConditions::STABLE; else SystemStateInfo.StateCondition = StateConditions::DRIFTING; return SystemStateInfo; } /// TODO: write description // TODO (future): think about saving the state information in a history SystemStateRelation compareSignalStateInformation( const std::vector> _SignalStateInfos) noexcept { bool inputsAreMatching = true; bool outputsAreMatching = true; std::size_t counter = 0; for (auto SSI : _SignalStateInfos) { if (this->SignalStateInfos.at(counter).StateID != SSI.StateID) { if (SSI.SignalProperty == SignalProperties::INPUT) inputsAreMatching = false; else // SignalProperties::OUTPUT outputsAreMatching = false; } counter++; } if (inputsAreMatching && outputsAreMatching) return SystemStateRelation::STATEISMATCHING; else if (inputsAreMatching && !outputsAreMatching) return SystemStateRelation::ONLYINPUTISMATCHING; else if (!inputsAreMatching && outputsAreMatching) return SystemStateRelation::ONLYOUTPUTISMATCHING; else return SystemStateRelation::STATEISMISMATCHING; } #ifdef ADDITIONAL_FUNCTIONS /// TODO: write description template void insertSignalStateInformation( const std::array, size> &Data) noexcept { ASSERT(size <= NumberOfSignals); std::size_t counter = 0; for (auto tmp : Data) { Signals.at(counter) = tmp; counter++; } } /// TODO: write description template std::enable_if_t>...>, void> insertSignalStateInformation(Types... Data) { // TODO (future): think about saving the state information in a history insertSignalStateInfos( std::array, sizeof...(Data)>( {Data...})); } // returns true if they are identical /// TODO: write description template bool compareSignalStateInformation( const std::array, size> &Data) noexcept { // TODO (future): think about saving the state information in a history std::size_t counter = 0; for (auto tmp : Data) { if (Signals.at(counter) != tmp) return false; counter++; } return true; } // checks only the given amount /// TODO: write description template std::enable_if_t>...>, bool> compareSignalStateInformation(Types... Data) { return compareSignalStateInfos( std::array, sizeof...(Data)>( {Data...})); } #endif /// Gives information about the current signal state. /// /// \return a struct SignalStateInformation that contains information about /// the current signal state. SystemStateInformation systemStateInformation(void) noexcept { return SystemStateInfo; } }; } // End namespace agent } // End namespace rosa #endif // ROSA_AGENT_SYSTEMSTATE_HPP diff --git a/lib/deluxe/DeluxeContext.cpp b/lib/deluxe/DeluxeContext.cpp index 7991c03..f20ce7b 100755 --- a/lib/deluxe/DeluxeContext.cpp +++ b/lib/deluxe/DeluxeContext.cpp @@ -1,201 +1,218 @@ //===-- deluxe/DeluxeContext.cpp --------------------------------*- C++ -*-===// // // The RoSA Framework // //===----------------------------------------------------------------------===// /// /// \file deluxe/DeluxeContext.cpp /// /// \author David Juhasz (david.juhasz@tuwien.ac.at) /// /// \date 2017-2019 /// /// \brief Implementation for rosa/deluxe/DeluxeContext.hpp. /// //===----------------------------------------------------------------------===// #define ROSA_LIB_DELUXE_DELUXECONTEXT_CPP // For including helper macros. #include "rosa/deluxe/DeluxeContext.hpp" #include +#include namespace rosa { namespace deluxe { std::unique_ptr DeluxeContext::create(const std::string &Name) noexcept { return std::unique_ptr(new DeluxeContext(Name)); } DeluxeContext::DeluxeContext(const std::string &Name) noexcept : System(DeluxeSystem::createSystem(Name)) { LOG_TRACE("DeluxeContext for '" + System->name() + "' is created."); } DeluxeContext::~DeluxeContext(void) noexcept { // \c rosa::deluxe::DeluxeContext::System is not used outside, just clean it. - for(auto U : DeluxeUnits) { + for (auto U : DeluxeUnits) { System->destroyAgent(U); } // \note \c System will be marked clean by SystemImpl::~SystemImpl. LOG_TRACE("DeluxeContext for '" + System->name() + "' prepared for destruction."); } Optional DeluxeContext::getExecutionPolicy(AgentHandle Unit) const noexcept { if (System->isDeluxeSensor(Unit)) { return {System->getDeluxeSensor(Unit)->executionPolicy()}; } else if (System->isDeluxeAgent(Unit)) { return {System->getDeluxeAgent(Unit)->executionPolicy()}; } else { return {}; } } DeluxeContext::ErrorCode DeluxeContext::setExecutionPolicy( AgentHandle Unit, std::unique_ptr &&ExecutionPolicy) noexcept { // Generate trace log. auto &Trace = LOG_TRACE_STREAM; Trace << "Setting execution policy of " << System->unwrapAgent(Unit).FullName << " to "; if (ExecutionPolicy) { Trace << "'" << ExecutionPolicy->dump() << "'\n"; } else { Trace << "[]\n"; DCRETERROR(ErrorCode::UnsuitableExecutionPolicy); } if (System->isDeluxeSensor(Unit)) { const bool Success = System->getDeluxeSensor(Unit)->setExecutionPolicy( std::move(ExecutionPolicy)); if (!Success) { DCRETERROR(ErrorCode::UnsuitableExecutionPolicy); } else { return ErrorCode::NoError; } } else if (System->isDeluxeAgent(Unit)) { const bool Success = System->getDeluxeAgent(Unit)->setExecutionPolicy( std::move(ExecutionPolicy)); if (!Success) { DCRETERROR(ErrorCode::UnsuitableExecutionPolicy); } else { return ErrorCode::NoError; } } else { DCRETERROR(ErrorCode::NotUnit); } } DeluxeContext::ErrorCode DeluxeContext::connectSensor(AgentHandle Agent, const size_t Pos, AgentHandle Sensor, const std::string &Description) noexcept { // Generate trace log. auto &Trace = LOG_TRACE_STREAM; Trace << "Establishing connection"; if (!Description.empty()) { Trace << " '" << Description << "'"; } Trace << " between '" << System->unwrapAgent(Sensor).FullName << "' and '" << System->unwrapAgent(Agent).FullName << "'\n"; // Make sure preconditions are met. if (!System->isDeluxeAgent(Agent)) { DCRETERROR(ErrorCode::NotAgent); } else if (!System->isDeluxeSensor(Sensor)) { DCRETERROR(ErrorCode::NotSensor); } auto A = System->getDeluxeAgent(Agent); auto S = System->getDeluxeSensor(Sensor); ASSERT(A && S); // Sanity check. if (Pos >= A->NumberOfInputs) { DCRETERROR(ErrorCode::WrongPosition); } else if (A->inputType(Pos) != S->OutputType || (!emptyToken(A->masterOutputType(Pos)) && A->masterOutputType(Pos) != S->MasterInputType)) { DCRETERROR(ErrorCode::TypeMismatch); } else if (A->slave(Pos)) { DCRETERROR(ErrorCode::AlreadyHasSlave); } else if (S->master()) { DCRETERROR(ErrorCode::AlreadyHasMaster); } // Do register. A->registerSlave(Pos, {Sensor}); S->registerMaster({Agent}); return ErrorCode::NoError; } DeluxeContext::ErrorCode DeluxeContext::connectAgents(AgentHandle Master, const size_t Pos, AgentHandle Slave, const std::string &Description) noexcept { // Generate trace log. auto &Trace = LOG_TRACE_STREAM; Trace << "Establishing connection"; if (!Description.empty()) { Trace << " '" << Description << "'"; } Trace << " between '" << System->unwrapAgent(Slave).FullName << "' and '" << System->unwrapAgent(Master).FullName << "'\n"; // Make sure preconditions are met. if (!(System->isDeluxeAgent(Master) && System->isDeluxeAgent(Slave))) { DCRETERROR(ErrorCode::NotAgent); } auto M = System->getDeluxeAgent(Master); auto S = System->getDeluxeAgent(Slave); ASSERT(M && S); // Sanity check. if (Pos >= M->NumberOfInputs) { DCRETERROR(ErrorCode::WrongPosition); } else if (M->inputType(Pos) != S->OutputType || (!emptyToken(M->masterOutputType(Pos)) && M->masterOutputType(Pos) != S->MasterInputType)) { DCRETERROR(ErrorCode::TypeMismatch); } else if (M->slave(Pos)) { DCRETERROR(ErrorCode::AlreadyHasSlave); } else if (S->master()) { DCRETERROR(ErrorCode::AlreadyHasMaster); } // Do register. M->registerSlave(Pos, {Slave}); S->registerMaster({Master}); return ErrorCode::NoError; } std::weak_ptr DeluxeContext::getSystem(void) const noexcept { return std::weak_ptr(System); } void DeluxeContext::initializeSimulation(void) noexcept { + LOG_INFO_STREAM << "Initializing simulation for " << System->name() + << ". Clearing all data sources.\n"; // Clear simulation data sources from sensors. for (auto U : DeluxeUnits) { if (auto S = System->getDeluxeSensor(U)) { S->clearSimulationDataSource(); } } } void DeluxeContext::simulate(const size_t NumCycles) const noexcept { + DEBUG(for (auto H + : DeluxeUnits) { + std::stringstream Message; + Message << System->unwrapAgent(H).FullName << " is a Deluxe " + << " " << (System->isDeluxeSensor(H) ? "Sensor" : "Agent"); + if (System->isDeluxeSensor(H)) + Message << " with it's data source " + << (!System->getDeluxeSensor(H)->simulationDataSourceIsSet() + ? "not " + : "set"); + Message << '\n'; + LOG_TRACE_STREAM << Message.str(); + }); + ASSERT(std::all_of( DeluxeUnits.begin(), DeluxeUnits.end(), [&](const AgentHandle &H) { return System->isDeluxeAgent(H) || System->isDeluxeSensor(H) && System->getDeluxeSensor(H)->simulationDataSourceIsSet(); })); for (size_t I = 1; I <= NumCycles; ++I) { LOG_TRACE("Simulation cycle: " + std::to_string(I)); for (auto U : DeluxeUnits) { U.sendMessage(Message::create(atoms::Trigger::Value)); } } } } // End namespace deluxe } // End namespace rosa