Skip to content
Snippets Groups Projects
Commit 742144f5 authored by Tim Übelhör's avatar Tim Übelhör
Browse files

Adaption of TcpEngineController

parent 05e260bf
Branches
No related tags found
No related merge requests found
#include "boost/program_options.hpp"
#include "ModeliFile.hpp"
#include "FmuEngine.hpp"
#include "TcpServer.hpp"
#include <iostream>
#include <thread>
#include "boost/program_options.hpp"
int main(int argc, char *argv[])
{
......@@ -36,10 +37,18 @@ int main(int argc, char *argv[])
port = vm["port"].as<unsigned short>();
}
auto fmuEngine = std::make_shared<Simulation::FmuEngine>(std::to_string(port));
// Extract the modeli file
// Load the modeli file into the engine
if (vm.count("modeli"))
{
throw std::exception("not implemented");
Files::ModeliFile modeliFile(vm["modeli"].as<std::string>());
for (auto fmuFile : modeliFile.GetFmus())
{
fmuEngine->AddFmu(fmuFile.InstanceName, fmuFile.Path);
}
for (auto channelLink : modeliFile.GetChannelLinks())
{
fmuEngine->AddChannelLink(channelLink);
}
}
// start the tcp server
Network::TcpServer server(port, fmuEngine);
......@@ -63,4 +72,3 @@ int main(int argc, char *argv[])
}
return 0;
}
\ No newline at end of file
......@@ -29,8 +29,8 @@ namespace Network
// Read the header
auto modeliMsg = GetModeliMessage(msg.data());
FmuEngine::FmiResult fmiResult{ 0, "" };
Simulation::FmiResult fmiResult;
Feedback feedback;
switch (modeliMsg->Command())
{
case (int)CommandEnum_KeepAlive:
......@@ -42,46 +42,48 @@ namespace Network
break;
case (int)CommandEnum_Play:
fmiResult = _fmuEngine->Play();
feedback = { fmiResult.Status, fmiResult.Message };
break;
case (int)CommandEnum_PlayFast:
fmiResult = playFast(modeliMsg);
feedback = playFast(modeliMsg);
break;
case (int)CommandEnum_Pause:
fmiResult = _fmuEngine->Pause();
feedback = { fmiResult.Status, fmiResult.Message };
break;
case (int)CommandEnum_Stop:
fmiResult = _fmuEngine->Stop();
feedback = { fmiResult.Status, fmiResult.Message };
break;
case (int)CommandEnum_AddFmu:
fmiResult = addFmu(modeliMsg);
feedback = addFmu(modeliMsg);
break;
case (int)CommandEnum_RemoveFmu:
fmiResult = removeFmu(modeliMsg);
feedback = removeFmu(modeliMsg);
break;
case (int)CommandEnum_ValueRefs:
fmiResult = receiveValueRefs(modeliMsg);
feedback = receiveValueRefs(modeliMsg);
break;
case (int)CommandEnum_AddChannelLinks:
fmiResult = addChannelLink(modeliMsg);
feedback = addChannelLink(modeliMsg);
break;
case (int)CommandEnum_RemoveChannelLinks:
fmiResult = removeChannelLink(modeliMsg);
feedback = removeChannelLink(modeliMsg);
break;
case (int)CommandEnum_Values:
fmiResult = setValues(modeliMsg);
feedback = setValues(modeliMsg);
break;
default:
std::cout << "Receive Command: Unknown" << std::endl;
fmiResult = { fmi2Warning, "Unknown Command " + std::to_string(modeliMsg->Command()) };
feedback = { fmi2Warning, "Unknown Command " + std::to_string(modeliMsg->Command()) };
break;
}
// Send feedback when the operation finished. Reply with the same JobNr.
sendFeedback(modeliMsg->JobNr(), fmiResult.Status, fmiResult.Message);
sendFeedback(modeliMsg->JobNr(), feedback.Status, feedback.Message);
}
// Extended parsing
FmuEngine::FmiResult TcpEngineController::addFmu(const ModeliMessage* msg)
Feedback TcpEngineController::addFmu(const ModeliMessage* msg)
{
// Check the datatype
if (msg->Data_type() != DataUnion_FmuFile)
......@@ -97,17 +99,19 @@ namespace Network
std::cout << "File receiving completed" << std::endl;
// Add the fmu to the engine
return _fmuEngine->AddFmu(data->InstanceName()->str(), fmuBuffer);
auto fmiStatus = _fmuEngine->AddFmu(data->InstanceName()->str(), fmuBuffer);
return { fmiStatus.Status, fmiStatus.Message };
}
FmuEngine::FmiResult TcpEngineController::removeFmu(const ModeliMessage * msg)
Feedback TcpEngineController::removeFmu(const ModeliMessage * msg)
{
if (msg->Data_type() != DataUnion_FmuFile)
{
return { fmi2Warning, "The type of Data is wrong." };
}
return _fmuEngine->RemoveFMU(msg->Data_as_FmuFile()->InstanceName()->str());
auto fmiStatus = _fmuEngine->RemoveFMU(msg->Data_as_FmuFile()->InstanceName()->str());
return { fmiStatus.Status, fmiStatus.Message };
}
FmuEngine::FmiResult TcpEngineController::receiveValueRefs(const ModeliMessage* msg)
Feedback TcpEngineController::receiveValueRefs(const ModeliMessage* msg)
{
// Check if the type of data is correct
if (msg->Data_type() != DataUnion_ValueRefs)
......@@ -140,9 +144,7 @@ namespace Network
if (valueRefs->StringVrs())
{
std::vector<unsigned int> stringVrs(valueRefs->StringVrs()->begin(), valueRefs->StringVrs()->end());
fmu->SetStringVr(stringVrs);
}
return{ fmi2OK, "" };
}
else
......@@ -150,7 +152,7 @@ namespace Network
return{ fmi2Warning, "Failed receiveValueRefs, fmu instance does not exist: " + std::string(valueRefs->InstanceName()->str()) };
}
}
FmuEngine::FmiResult TcpEngineController::addChannelLink(const ModeliMessage* msg)
Feedback TcpEngineController::addChannelLink(const ModeliMessage* msg)
{
if (msg->Data_type() != DataUnion_ChannelLink)
{
......@@ -159,16 +161,17 @@ namespace Network
else
{
auto link = msg->Data_as_ChannelLink();
return _fmuEngine->AddChannelLink(
auto fmiStatus = _fmuEngine->AddChannelLink(
link->MasterInstanceName()->str(),
link->SlaveInstanceName()->str(),
link->MasterVr(),
link->SlaveVr(),
link->Factor(),
link->Shift());
return { fmiStatus.Status, fmiStatus.Message };
}
}
FmuEngine::FmiResult TcpEngineController::removeChannelLink(const ModeliMessage* msg)
Feedback TcpEngineController::removeChannelLink(const ModeliMessage* msg)
{
if (msg->Data_type() != DataUnion_ChannelLink)
{
......@@ -177,14 +180,15 @@ namespace Network
else
{
auto link = msg->Data_as_ChannelLink();
return _fmuEngine->RemoveChannelLink(
auto fmiStatus = _fmuEngine->RemoveChannelLink(
link->MasterInstanceName()->str(),
link->SlaveInstanceName()->str(),
link->MasterVr(),
link->SlaveVr());
return { fmiStatus.Status, fmiStatus.Message };
}
}
FmuEngine::FmiResult TcpEngineController::playFast(const ModeliMessage * msg)
Feedback TcpEngineController::playFast(const ModeliMessage * msg)
{
auto modeliMsgDataType = msg->Data_type();
if (modeliMsgDataType != DataUnion_Time)
......@@ -193,10 +197,11 @@ namespace Network
}
else
{
return _fmuEngine->PlayFast(msg->Data_as_Time()->Value());
auto fmiStatus = _fmuEngine->PlayFast(msg->Data_as_Time()->Value());
return { fmiStatus.Status, fmiStatus.Message };
}
}
FmuEngine::FmiResult TcpEngineController::setValues(const ModeliMessage * msg)
Feedback TcpEngineController::setValues(const ModeliMessage * msg)
{
if (msg->Data_type() != DataUnion_Values)
{
......@@ -204,7 +209,7 @@ namespace Network
}
auto data = msg->Data_as_Values();
FmuEngine::FmiResult res = { fmi2OK, data->InstanceName()->str() };
Feedback feedback = { fmi2OK, data->InstanceName()->str() };
// Only if the fmu exists
if (auto fmuLifetimeWrapper = _fmuEngine->FindFmu(data->InstanceName()->str()))
{
......@@ -212,7 +217,11 @@ namespace Network
// Integer
if (data->IntVrs() && data->IntValues())
{
fmu->SetInteger(data->IntVrs()->data(), data->IntVrs()->size(), data->IntValues()->data());
int setRes = fmu->SetInteger(data->IntVrs()->data(), data->IntVrs()->size(), data->IntValues()->data());
if (setRes > feedback.Status)
{
}
}
// Real
if (data->RealVrs() && data->RealValues())
......
......@@ -7,12 +7,20 @@
#include "IConnectionObserver.hpp"
#include "ModeliProtocol_generated.h"
#include "FmuEngine.hpp"
namespace Simulation
{
class FmuEngine;
}
using Simulation::FmuEngine;
namespace Network
{
struct Feedback
{
int Status;
std::string Message;
};
class TcpEngineController : public IConnectionObserver
{
public:
......@@ -30,21 +38,21 @@ namespace Network
virtual void MessageArrived(const std::vector<unsigned char>& msg) override;
/// Receive a whole Fmu
FmuEngine::FmiResult addFmu(const Protocol::ModeliMessage* msg);
Feedback addFmu(const Protocol::ModeliMessage* msg);
/// Remove a fmu
FmuEngine::FmiResult removeFmu(const Protocol::ModeliMessage* msg);
Feedback removeFmu(const Protocol::ModeliMessage* msg);
/// Receives all the default valueReferences
FmuEngine::FmiResult receiveValueRefs(const Protocol::ModeliMessage* msg);
Feedback receiveValueRefs(const Protocol::ModeliMessage* msg);
/// Adds a collection of channelLinks
FmuEngine::FmiResult addChannelLink(const Protocol::ModeliMessage* msg);
Feedback addChannelLink(const Protocol::ModeliMessage* msg);
/// Removes a collection of channelLinks
FmuEngine::FmiResult removeChannelLink(const Protocol::ModeliMessage* msg);
Feedback removeChannelLink(const Protocol::ModeliMessage* msg);
/// Starts playing in fast mode
FmuEngine::FmiResult playFast(const Protocol::ModeliMessage* msg);
Feedback playFast(const Protocol::ModeliMessage* msg);
/// Set values in a fmu
FmuEngine::FmiResult setValues(const Protocol::ModeliMessage* msg);
Feedback setValues(const Protocol::ModeliMessage* msg);
void sendFeedback(int jobNr, int result, const std::string message);
};
......
......@@ -3,6 +3,8 @@
#include "TcpServer.hpp"
#include "TcpEngineController.hpp"
#include "TcpEngineObserver.hpp"
// Simulation
#include "FmuEngine.hpp"
namespace ph = std::placeholders;
......
// Simulation
#include "FmuFile.hpp"
#include "FmuEngine.hpp"
// FMI
#include "CoSimFmu.h"
// std
#include <iostream>
......@@ -197,7 +196,7 @@ namespace Simulation
return std::chrono::duration_cast<double_seconds>(duration).count();
}
FmuEngine::FmiResult FmuEngine::startSimulation()
FmiResult FmuEngine::startSimulation()
{
// Play from initialized or stopped state
if (!_simulating)
......@@ -233,7 +232,7 @@ namespace Simulation
_observers.remove(observer);
}
FmuEngine::FmiResult FmuEngine::Play()
FmiResult FmuEngine::Play()
{
// Play infinite
_endDuration = std::chrono::milliseconds(0);
......@@ -241,7 +240,7 @@ namespace Simulation
_playFast = false;
return startSimulation();
}
FmuEngine::FmiResult FmuEngine::PlayFast(double endTime_sec)
FmiResult FmuEngine::PlayFast(double endTime_sec)
{
// Update the _endTime
_endDuration = std::chrono::milliseconds(static_cast<unsigned long>(endTime_sec * 1000));
......@@ -250,7 +249,7 @@ namespace Simulation
return startSimulation();
}
// Stop the simulation thread
FmuEngine::FmiResult FmuEngine::Pause()
FmiResult FmuEngine::Pause()
{
// Only try to obtain ownership over the thread without blocking the current thread
_simulating = false;
......@@ -259,7 +258,7 @@ namespace Simulation
return{ fmi2OK,"" };
}
// Stop the thread and reset the simulation
FmuEngine::FmiResult FmuEngine::Stop()
FmiResult FmuEngine::Stop()
{
// Stop simulation
_simulating = false;
......@@ -299,7 +298,7 @@ namespace Simulation
return res;
}
FmuEngine::FmiResult FmuEngine::initializeFmu(std::shared_ptr<CoSimFmu> fmu)
FmiResult FmuEngine::initializeFmu(std::shared_ptr<CoSimFmu> fmu)
{
// No error estimation and no pre-defined stoptime -> 10.0 is meaningless
int status = fmu->SetupExperiment(fmi2False, 0, 0, fmi2False, 0);
......@@ -339,23 +338,36 @@ namespace Simulation
}
}
FmuEngine::FmiResult FmuEngine::AddChannelLink(const std::string& masterInstanceName, const std::string& slaveInstanceName,
unsigned int masterValueRef, unsigned int slaveValueRef, double factor, double shift)
FmiResult FmuEngine::AddChannelLink(ChannelLink channelLink)
{
// Check existance of instances
if (!FindFmu(masterInstanceName))
if (!FindFmu(channelLink.MasterInstanceName))
{
onLog("FmuEngine", fmi2Warning, "FmuEngine",
"MasterInstanceName of ChannelLink not found: " + masterInstanceName);
"MasterInstanceName of ChannelLink not found: " + channelLink.MasterInstanceName);
return{ fmi2Warning, "One of the channelLinks is invalid. See log." };
}
if (!FindFmu(slaveInstanceName))
if (!FindFmu(channelLink.SlaveInstanceName))
{
onLog("FmuEngine", fmi2Warning, "FmuEngine",
"SlaveInstanceName of ChannelLink not found: " + slaveInstanceName);
"SlaveInstanceName of ChannelLink not found: " + channelLink.SlaveInstanceName);
return{ fmi2Warning, "One of the channelLinks is invalid. See log." };
}
// Add
_channelLinks.push_back(channelLink);
return { fmi2OK,"" };
}
FmiResult FmuEngine::RemoveChannelLink(ChannelLink channelLink)
{
_channelLinks.remove(channelLink);
return { fmi2OK,"" };
}
FmiResult FmuEngine::AddChannelLink(const std::string& masterInstanceName, const std::string& slaveInstanceName,
unsigned int masterValueRef, unsigned int slaveValueRef, double factor, double shift)
{
// Create the channelLink
ChannelLink channelLink;
channelLink.MasterInstanceName = masterInstanceName;
......@@ -364,11 +376,10 @@ namespace Simulation
channelLink.SlaveValueRef = slaveValueRef;
channelLink.Factor = factor;
channelLink.Shift = shift;
// Add
_channelLinks.push_back(channelLink);
return { fmi2OK,"" };
// Add it!
return AddChannelLink(channelLink);
}
FmuEngine::FmiResult FmuEngine::RemoveChannelLink(const std::string& masterInstanceName, const std::string& slaveInstanceName,
FmiResult FmuEngine::RemoveChannelLink(const std::string& masterInstanceName, const std::string& slaveInstanceName,
unsigned int masterValueRef, unsigned int slaveValueRef)
{
// Create the channelLink
......@@ -377,11 +388,11 @@ namespace Simulation
channelLink.SlaveInstanceName = slaveInstanceName;
channelLink.MasterValueRef = masterValueRef;
channelLink.SlaveValueRef = slaveValueRef;
_channelLinks.remove(channelLink);
return { fmi2OK,"" };
// Remove it!
return RemoveChannelLink(channelLink);
}
FmuEngine::FmiResult FmuEngine::addFmu(std::shared_ptr<Files::FmuFile> fmuFile)
FmiResult FmuEngine::addFmu(std::shared_ptr<FmuFile> fmuFile)
{
// Check if the instanceName is in use
if (FindFmu(fmuFile->GetInstanceName()))
......@@ -419,7 +430,7 @@ namespace Simulation
return{ fmi2OK,"" };
}
FmuEngine::FmiResult FmuEngine::AddFmu(std::string instanceName, std::string path)
FmiResult FmuEngine::AddFmu(std::string instanceName, std::string path)
{
// Check if the instanceName is in use
if (FindFmu(instanceName))
......@@ -429,10 +440,10 @@ namespace Simulation
}
// Add the fmu from file
addFmu(std::make_shared<Files::FmuFile>(path, _controllerId, instanceName));
return addFmu(std::make_shared<FmuFile>(path, _controllerId, instanceName));
}
FmuEngine::FmiResult FmuEngine::AddFmu(std::string instanceName, const std::vector<unsigned char> &bytes)
FmiResult FmuEngine::AddFmu(std::string instanceName, const std::vector<unsigned char> &bytes)
{
// Check if the instanceName is in use
if (FindFmu(instanceName))
......@@ -441,10 +452,10 @@ namespace Simulation
return{ fmi2Error, "The instanceName already exists: " + instanceName };
}
// Add the fmu from file
addFmu(std::make_shared<Files::FmuFile>(bytes, _controllerId, instanceName));
return addFmu(std::make_shared<FmuFile>(bytes, _controllerId, instanceName));
}
FmuEngine::FmiResult FmuEngine::RemoveFMU(std::string instanceName)
FmiResult FmuEngine::RemoveFMU(std::string instanceName)
{
// Make sure we stopped the simulation
Stop();
......@@ -452,7 +463,7 @@ namespace Simulation
if (auto fmu = FindFmu(instanceName))
{
// Remove the fmu from the collection, which will free the fmu
int n_removed = _fmus.erase(instanceName);
_fmus.erase(instanceName);
}
else
{
......@@ -461,7 +472,7 @@ namespace Simulation
return{ fmi2OK,"" };
}
boost::optional<FmuEngine::FmuLifetimeWrapper> FmuEngine::FindFmu(std::string instanceName)
boost::optional<FmuLifetimeWrapper> FmuEngine::FindFmu(std::string instanceName)
{
auto iter = _fmus.find(instanceName);
if (iter == _fmus.end())
......
......@@ -5,7 +5,6 @@
#include "boost/optional.hpp"
#include "ChannelLink.h"
#include "FmuFile.hpp"
#include "IEngineObserver.hpp"
#include <atomic>
#include <list>
......@@ -21,17 +20,19 @@ namespace NativeFmu
class CoSimFmu;
}
using NativeFmu::CoSimFmu;
namespace Files
{
class FmuFile;
}
using Files::FmuFile;
namespace Simulation
{
class FmuEngine
{
public:
/// We need a CoSimFmu and the files with the same lifetime
struct FmuLifetimeWrapper
{
std::shared_ptr<CoSimFmu> CoSimFmu;
std::shared_ptr<Files::FmuFile> FmuFile;
std::shared_ptr<FmuFile> FmuFile;
};
/// Return status & message
struct FmiResult
......@@ -40,6 +41,9 @@ namespace Simulation
std::string Message;
};
class FmuEngine
{
public:
///< Creates a new instance of the FmuEngine
FmuEngine(
std::string id ///< A unique identification, used to create a dir where the models will be stored
......@@ -61,6 +65,10 @@ namespace Simulation
/// Halts the simulation and resets it to t=0.
FmiResult Stop();
/// Add a ChannelLink
FmiResult AddChannelLink(ChannelLink channelLink);
/// Remove a ChannelLink
FmiResult RemoveChannelLink(ChannelLink channelLink);
/// Add a ChannelLink
FmiResult AddChannelLink(const std::string& masterInstanceName, const std::string& slaveInstanceName,
unsigned int masterValueRef, unsigned int slaveValueRef, double factor, double shift);
......@@ -108,7 +116,7 @@ namespace Simulation
/// Add a fmu which was loaded by FmuFile class
FmiResult addFmu(
std::shared_ptr<Files::FmuFile> fmuFile ///< The loaded file
std::shared_ptr<FmuFile> fmuFile ///< The loaded file
);
/// Prepares and runs the simulation loop in a new thread
FmiResult startSimulation();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment