ecos: added mirror objects for ECoS internal objects

Dieser Commit ist enthalten in:
Reinder Feenstra 2021-12-20 00:23:31 +01:00
Ursprung 4df09ae5e0
Commit 6139fa366c
22 geänderte Dateien mit 1035 neuen und 87 gelöschten Zeilen

Datei anzeigen

@ -105,6 +105,8 @@ file(GLOB SOURCES
"src/hardware/protocol/ecos/*.cpp"
"src/hardware/protocol/ecos/iohandler/*.hpp"
"src/hardware/protocol/ecos/iohandler/*.cpp"
"src/hardware/protocol/ecos/object/*.hpp"
"src/hardware/protocol/ecos/object/*.cpp"
"src/hardware/protocol/loconet/*.hpp"
"src/hardware/protocol/loconet/*.cpp"
"src/hardware/protocol/loconet/iohandler/*.hpp"

Datei anzeigen

@ -23,6 +23,10 @@
#include "kernel.hpp"
#include <algorithm>
#include "messages.hpp"
#include "object/ecos.hpp"
#include "object/locomotivemanager.hpp"
#include "object/switchmanager.hpp"
#include "object/feedbackmanager.hpp"
#include "../../decoder/decoder.hpp"
#include "../../decoder/decoderchangeflags.hpp"
#include "../../../utils/setthreadname.hpp"
@ -94,9 +98,7 @@ void Kernel::start()
{
assert(m_ioHandler);
assert(!m_started);
// reset all state values
m_emergencyStop = TriState::Undefined;
assert(m_objects.empty());
m_thread = std::thread(
[this]()
@ -111,20 +113,10 @@ void Kernel::start()
{
m_ioHandler->start();
for(auto id : {ObjectId::ecos, ObjectId::locManager, ObjectId::switchManager, ObjectId::feedbackManager})
send(request(id, {Option::view}));
send(get(ObjectId::ecos, {Option::info}));
// query some lists
send(queryObjects(ObjectId::locManager, {Option::addr, Option::protocol}));
send(queryObjects(ObjectId::switchManager, {Option::addr}));
send(queryObjects(ObjectId::feedbackManager));
// query an object
send(request(1000, {Option::view}));
send(get(1000, {Option::addr}));
send(get(1000, {Option::name}));
m_objects.add(std::make_unique<ECoS>(*this));
m_objects.add(std::make_unique<LocomotiveManager>(*this));
m_objects.add(std::make_unique<SwitchManager>(*this));
m_objects.add(std::make_unique<FeedbackManager>(*this));
if(m_onStarted)
EventLoop::call(
@ -151,6 +143,8 @@ void Kernel::stop()
m_thread.join();
m_objects.clear();
#ifndef NDEBUG
m_started = false;
#endif
@ -160,90 +154,48 @@ void Kernel::receive(std::string_view message)
{
if(m_config.debugLogRXTX)
{
std::string msg{message};
std::replace(msg.begin(), msg.end(), '\n', ';');
std::string msg{rtrim(message, {'\r', '\n'})};
std::replace_if(msg.begin(), msg.end(), [](char c){ return c == '\r' || c == '\n'; }, ';');
EventLoop::call([this, msg](){ Log::log(m_logId, LogMessage::D2002_RX_X, msg); });
}
Reply reply;
Event event;
if(parseReply(message, reply))
if(Reply reply; parseReply(message, reply))
{
receiveReply(reply);
auto it = m_objects.find(reply.objectId);
if(it != m_objects.end())
it->second->receiveReply(reply);
}
else if(parseEvent(message, event))
else if(Event event; parseEvent(message, event))
{
receiveEvent(event);
auto it = m_objects.find(event.objectId);
if(it != m_objects.end())
it->second->receiveEvent(event);
}
else
{}// EventLoop::call([this]() { Log::log(m_logId, LogMessage::E2018_ParseError); });
}
void Kernel::receiveReply(const Reply& reply)
ECoS& Kernel::ecos()
{
if(reply.objectId == ObjectId::ecos)
{
if(reply.command == Command::set)
{
if(reply.options.size() == 1)
{
if(reply.options[0] == Option::stop)
{
if(m_emergencyStop != TriState::True)
{
m_emergencyStop = TriState::True;
if(m_onEmergencyStop)
EventLoop::call([this]() { m_onEmergencyStop(); });
}
}
else if(reply.options[0] == Option::go)
{
if(m_emergencyStop != TriState::False)
{
m_emergencyStop = TriState::False;
if(m_onGo)
EventLoop::call([this]() { m_onGo(); });
}
}
}
}
else if(reply.command == Command::get)
{
if(reply.options.size() == 1)
{
if(reply.options[0] == Option::info)
{
//! @todo
}
}
}
}
return static_cast<ECoS&>(*m_objects[ObjectId::ecos]);
}
void Kernel::receiveEvent(const Event& event)
void Kernel::ecosGoChanged(TriState value)
{
(void)event;
if(value == TriState::False && m_onEmergencyStop)
EventLoop::call([this]() { m_onEmergencyStop(); });
else if(value == TriState::True && m_onGo)
EventLoop::call([this]() { m_onGo(); });
}
void Kernel::emergencyStop()
{
m_ioContext.post(
[this]()
{
if(m_emergencyStop != TriState::True)
send(set(ObjectId::ecos, {Option::stop}));
});
m_ioContext.post([this]() { ecos().stop(); });
}
void Kernel::go()
{
m_ioContext.post(
[this]()
{
if(m_emergencyStop != TriState::False)
send(set(ObjectId::ecos, {Option::go}));
});
m_ioContext.post([this]() { ecos().go(); });
}
void Kernel::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber)

Datei anzeigen

@ -28,6 +28,7 @@
#include <traintastic/enum/tristate.hpp>
#include "config.hpp"
#include "iohandler/iohandler.hpp"
#include "object/object.hpp"
class Decoder;
enum class DecoderChangeFlags;
@ -37,19 +38,33 @@ class OutputController;
namespace ECoS {
struct Reply;
struct Event;
class ECoS;
class Kernel
{
friend class Object;
friend class ECoS;
private:
class Objects : public std::unordered_map<uint16_t, std::unique_ptr<Object>>
{
public:
template<class T>
inline void add(std::unique_ptr<T> object)
{
const auto id = object->id();
emplace(id, std::move(object));
}
};
boost::asio::io_context m_ioContext;
std::unique_ptr<IOHandler> m_ioHandler;
std::thread m_thread;
std::string m_logId;
std::function<void()> m_onStarted;
TriState m_emergencyStop;
Objects m_objects;
std::function<void()> m_onGo;
std::function<void()> m_onEmergencyStop;
@ -66,8 +81,8 @@ class Kernel
void setIOHandler(std::unique_ptr<IOHandler> handler);
void receiveReply(const Reply& reply);
void receiveEvent(const Event& event);
ECoS& ecos();
void ecosGoChanged(TriState value);
public:// REMOVE!! just for testing
void postSend(const std::string& message)

Datei anzeigen

@ -1,3 +1,25 @@
/**
* server/src/hardware/protocol/ecos/messages.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "messages.hpp"
#include <cassert>
#include <charconv>
@ -102,4 +124,10 @@ bool parseEvent(std::string_view message, Event& event)
return false;
}
bool parseId(std::string_view line, uint16_t& id)
{
auto r = std::from_chars(line.data(), line.data() + line.size() - 1, id);
return r.ec == std::errc();
}
}

Datei anzeigen

@ -43,7 +43,7 @@ struct ObjectId
{
static constexpr uint16_t ecos = 1;
static constexpr uint16_t programmingTrack = 5;
static constexpr uint16_t locManager = 10;
static constexpr uint16_t locomotiveManager = 10;
static constexpr uint16_t switchManager = 11;
static constexpr uint16_t shuttleTrainControl = 12;
static constexpr uint16_t deviceManager = 20;
@ -51,15 +51,22 @@ struct ObjectId
static constexpr uint16_t feedbackManager = 26;
static constexpr uint16_t booster = 27;
static constexpr uint16_t controlDesk = 31;
static constexpr uint16_t s88 = 100;
static constexpr uint16_t ecosDetector = 200;
};
struct Option
{
static constexpr std::string_view addr = "addr";
static constexpr std::string_view dir = "dir";
static constexpr std::string_view go = "go";
static constexpr std::string_view info = "info";
static constexpr std::string_view mode = "mode";
static constexpr std::string_view name = "name";
static constexpr std::string_view ports = "ports";
static constexpr std::string_view protocol = "protocol";
static constexpr std::string_view speedStep = "speedstep";
static constexpr std::string_view state = "state";
static constexpr std::string_view status = "status";
static constexpr std::string_view stop = "stop";
static constexpr std::string_view view = "view";
@ -73,7 +80,7 @@ enum class Status : uint32_t
struct Reply
{
std::string_view command;
uint32_t objectId;
uint16_t objectId;
std::vector<std::string_view> options;
std::vector<std::string_view> lines;
Status status;
@ -82,7 +89,7 @@ struct Reply
struct Event
{
uint32_t objectId;
uint16_t objectId;
};
inline std::string buildCommand(std::string_view command, uint16_t objectId, std::initializer_list<std::string_view> options)
@ -133,6 +140,8 @@ inline std::string release(uint16_t objectId, std::initializer_list<std::string_
bool parseReply(std::string_view message, Reply& reply);
bool parseEvent(std::string_view message, Event& event);
bool parseId(std::string_view line, uint16_t& id);
}
#endif

Datei anzeigen

@ -0,0 +1,96 @@
/**
* server/src/hardware/protocol/ecos/object/ecos.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "ecos.hpp"
#include <cassert>
#include "../kernel.hpp"
#include "../messages.hpp"
namespace ECoS {
ECoS::ECoS(Kernel& kernel)
: Object(kernel, ObjectId::ecos)
{
requestView();
send(get(m_id, {Option::info}));
}
bool ECoS::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
if(reply.command == Command::set)
{
if(reply.options.size() == 1)
{
if(reply.options[0] == Option::stop)
{
if(m_go != TriState::False)
{
m_go = TriState::False;
m_kernel.ecosGoChanged(m_go);
}
}
else if(reply.options[0] == Option::go)
{
if(m_go != TriState::True)
{
m_go = TriState::True;
m_kernel.ecosGoChanged(m_go);
}
}
}
}
else if(reply.command == Command::get)
{
if(reply.options.size() == 1)
{
if(reply.options[0] == Option::info)
{
//! @todo
}
}
}
return Object::receiveReply(reply);
}
bool ECoS::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return Object::receiveEvent(event);
}
void ECoS::go()
{
if(m_go != TriState::True)
send(set(m_id, {Option::go}));
}
void ECoS::stop()
{
if(m_go != TriState::False)
send(set(m_id, {Option::stop}));
}
}

Datei anzeigen

@ -0,0 +1,50 @@
/**
* server/src/hardware/protocol/ecos/object/ecos.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_ECOS_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_ECOS_HPP
#include "object.hpp"
#include <traintastic/enum/tristate.hpp>
namespace ECoS {
class Kernel;
class ECoS final : public Object
{
private:
TriState m_go = TriState::Undefined;
public:
ECoS(Kernel& kernel);
bool receiveReply(const Reply& reply) final;
bool receiveEvent(const Event& event) final;
void go();
void stop();
};
}
#endif

Datei anzeigen

@ -0,0 +1,50 @@
/**
* server/src/hardware/protocol/ecos/object/feedback.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "feedback.hpp"
#include <cassert>
#include "../messages.hpp"
namespace ECoS {
const std::initializer_list<std::string_view> Feedback::options = {Option::addr, Option::protocol, Option::state, Option::ports};
Feedback::Feedback(Kernel& kernel, uint16_t id)
: Object(kernel, id)
{
}
bool Feedback::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
return Object::receiveReply(reply);
}
bool Feedback::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return Object::receiveEvent(event);
}
}

Datei anzeigen

@ -0,0 +1,46 @@
/**
* server/src/hardware/protocol/ecos/object/feedback.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_FEEDBACK_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_FEEDBACK_HPP
#include "object.hpp"
#include "../messages.hpp"
namespace ECoS {
class Kernel;
class Feedback final : public Object
{
public:
static const std::initializer_list<std::string_view> options;
Feedback(Kernel& kernel, uint16_t id);
bool receiveReply(const Reply& reply) final;
bool receiveEvent(const Event& event) final;
};
}
#endif

Datei anzeigen

@ -0,0 +1,65 @@
/**
* server/src/hardware/protocol/ecos/object/feedbackmanager.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "feedbackmanager.hpp"
#include <cassert>
#include "feedback.hpp"
#include "../messages.hpp"
namespace ECoS {
FeedbackManager::FeedbackManager(Kernel& kernel)
: Object(kernel, ObjectId::feedbackManager)
{
requestView();
send(queryObjects(m_id, Feedback::options));
send(request(ObjectId::s88, {Option::view}));
send(request(ObjectId::ecosDetector, {Option::view}));
}
bool FeedbackManager::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
if(reply.command == Command::queryObjects)
{
for(std::string_view line : reply.lines)
{
if(uint16_t id; parseId(line, id) && !objectExists(id))
{
addObject(std::make_unique<Feedback>(m_kernel, id));
}
}
return true;
}
return Object::receiveReply(reply);
}
bool FeedbackManager::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return Object::receiveEvent(event);
}
}

Datei anzeigen

@ -0,0 +1,43 @@
/**
* server/src/hardware/protocol/ecos/object/feedbackmanager.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_FEEDBACKMANAGER_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_FEEDBACKMANAGER_HPP
#include "object.hpp"
namespace ECoS {
class Kernel;
class FeedbackManager final : public Object
{
public:
FeedbackManager(Kernel& kernel);
bool receiveReply(const Reply& reply) final;
bool receiveEvent(const Event& event) final;
};
}
#endif

Datei anzeigen

@ -0,0 +1,51 @@
/**
* server/src/hardware/protocol/ecos/object/locomotive.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "locomotive.hpp"
#include <cassert>
#include "../messages.hpp"
namespace ECoS {
const std::initializer_list<std::string_view> Locomotive::options = {Option::addr, Option::protocol, Option::state, Option::speedStep};
Locomotive::Locomotive(Kernel& kernel, uint16_t id)
: Object(kernel, id)
{
requestView();
}
bool Locomotive::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
return Object::receiveReply(reply);
}
bool Locomotive::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return Object::receiveEvent(event);
}
}

Datei anzeigen

@ -0,0 +1,65 @@
/**
* server/src/hardware/protocol/ecos/object/locomotive.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_LOCOMOTIVE_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_LOCOMOTIVE_HPP
#include "object.hpp"
#include "../messages.hpp"
namespace ECoS {
class Kernel;
class Locomotive final : public Object
{
public:
enum class Protocol
{
Unknown = 0,
MM14 = 1,
MM27 = 2,
MM28 = 3,
DCC14 = 4,
DCC28 = 5,
DCC128 = 6,
SX32 = 7,
MMFKT = 8,
};
private:
Protocol m_protocol = Protocol::Unknown;
public:
static const std::initializer_list<std::string_view> options;
Locomotive(Kernel& kernel, uint16_t id);
bool receiveReply(const Reply& reply) final;
bool receiveEvent(const Event& event) final;
Protocol protocol() const { return m_protocol; }
};
}
#endif

Datei anzeigen

@ -0,0 +1,63 @@
/**
* server/src/hardware/protocol/ecos/object/locomotivemanager.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "locomotivemanager.hpp"
#include <cassert>
#include "locomotive.hpp"
#include "../messages.hpp"
namespace ECoS {
LocomotiveManager::LocomotiveManager(Kernel& kernel)
: Object(kernel, ObjectId::locomotiveManager)
{
requestView();
send(queryObjects(m_id, Locomotive::options));
}
bool LocomotiveManager::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
if(reply.command == Command::queryObjects)
{
for(std::string_view line : reply.lines)
{
if(uint16_t id; parseId(line, id) && !objectExists(id))
{
addObject(std::make_unique<Locomotive>(m_kernel, id));
}
}
return true;
}
return Object::receiveReply(reply);
}
bool LocomotiveManager::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return Object::receiveEvent(event);
}
}

Datei anzeigen

@ -0,0 +1,43 @@
/**
* server/src/hardware/protocol/ecos/object/locomotivemanager.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_LOCOMOTIVEMANAGER_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_LOCOMOTIVEMANAGER_HPP
#include "object.hpp"
namespace ECoS {
class Kernel;
class LocomotiveManager final : public Object
{
public:
LocomotiveManager(Kernel& kernel);
bool receiveReply(const Reply& reply) final;
bool receiveEvent(const Event& event) final;
};
}
#endif

Datei anzeigen

@ -0,0 +1,71 @@
/**
* server/src/hardware/protocol/ecos/object/object.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "object.hpp"
#include <cassert>
#include "../messages.hpp"
#include "../kernel.hpp"
namespace ECoS {
Object::Object(Kernel& kernel, uint16_t id)
: m_kernel{kernel}
, m_id{id}
{
}
bool Object::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
return false;
}
bool Object::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return false;
}
void Object::requestView()
{
if(!m_isViewActive)
send(request(m_id, {Option::view}));
}
void Object::send(std::string_view message)
{
m_kernel.send(message);
}
bool Object::objectExists(uint16_t objectId) const
{
return m_kernel.m_objects.find(objectId) != m_kernel.m_objects.end();
}
void Object::addObject(std::unique_ptr<Object> object)
{
m_kernel.m_objects.add(std::move(object));
}
}

Datei anzeigen

@ -0,0 +1,66 @@
/**
* server/src/hardware/protocol/ecos/object/object.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_OBJECT_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_OBJECT_HPP
#include <cstdint>
#include <memory>
#include <string_view>
namespace ECoS {
class Kernel;
struct Reply;
struct Event;
class Object
{
protected:
Kernel& m_kernel;
const uint16_t m_id;
bool m_isViewActive = false;
void send(std::string_view message);
bool objectExists(uint16_t objectId) const;
void addObject(std::unique_ptr<Object> object);
public:
Object(const Object&) = delete;
Object& operator =(const Object&) = delete;
Object(Kernel& kernel, uint16_t id);
virtual ~Object() = default;
virtual bool receiveReply(const Reply& reply);
virtual bool receiveEvent(const Event& event);
inline uint16_t id() const { return m_id; }
inline bool isViewActive() const { return m_isViewActive; }
void requestView();
};
}
#endif

Datei anzeigen

@ -0,0 +1,51 @@
/**
* server/src/hardware/protocol/ecos/object/switch.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "switch.hpp"
#include <cassert>
#include "../messages.hpp"
namespace ECoS {
const std::initializer_list<std::string_view> Switch::options = {Option::addr, Option::protocol, Option::state, Option::mode};
Switch::Switch(Kernel& kernel, uint16_t id)
: Object(kernel, id)
{
requestView();
}
bool Switch::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
return Object::receiveReply(reply);
}
bool Switch::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return Object::receiveEvent(event);
}
}

Datei anzeigen

@ -0,0 +1,59 @@
/**
* server/src/hardware/protocol/ecos/object/switch.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_SWITCH_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_SWITCH_HPP
#include "object.hpp"
#include "../messages.hpp"
namespace ECoS {
class Kernel;
class Switch final : public Object
{
public:
enum class Protocol
{
Unknown = 0,
DCC = 1,
MM = 2,
};
private:
Protocol m_protocol = Protocol::Unknown;
public:
static const std::initializer_list<std::string_view> options;
Switch(Kernel& kernel, uint16_t id);
bool receiveReply(const Reply& reply) final;
bool receiveEvent(const Event& event) final;
Protocol protocol() const { return m_protocol; }
};
}
#endif

Datei anzeigen

@ -0,0 +1,64 @@
/**
* server/src/hardware/protocol/ecos/object/switchmanager.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "switchmanager.hpp"
#include <cassert>
#include "switch.hpp"
#include "../messages.hpp"
namespace ECoS {
SwitchManager::SwitchManager(Kernel& kernel)
: Object(kernel, ObjectId::switchManager)
{
requestView();
send(queryObjects(m_id, Switch::options));
}
bool SwitchManager::receiveReply(const Reply& reply)
{
assert(reply.objectId == m_id);
if(reply.command == Command::queryObjects)
{
for(std::string_view line : reply.lines)
{
if(uint16_t id; parseId(line, id) && !objectExists(id))
{
addObject(std::make_unique<Switch>(m_kernel, id));
}
}
return true;
}
return Object::receiveReply(reply);
}
bool SwitchManager::receiveEvent(const Event& event)
{
assert(event.objectId == m_id);
return Object::receiveEvent(event);
}
}

Datei anzeigen

@ -0,0 +1,43 @@
/**
* server/src/hardware/protocol/ecos/object/switchmanager.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_SWITCHMANAGER_HPP
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_ECOS_OBJECT_SWITCHMANAGER_HPP
#include "object.hpp"
namespace ECoS {
class Kernel;
class SwitchManager final : public Object
{
public:
SwitchManager(Kernel& kernel);
bool receiveReply(const Reply& reply) final;
bool receiveEvent(const Event& event) final;
};
}
#endif

Datei anzeigen

@ -24,6 +24,7 @@
#define TRAINTASTIC_SERVER_UTILS_RTRIM_HPP
#include <string_view>
#include <algorithm>
constexpr std::string_view rtrim(std::string_view s, char c)
{
@ -31,7 +32,22 @@ constexpr std::string_view rtrim(std::string_view s, char c)
return {};
size_t size = s.size() - 1;
while(s.data()[--size] == c)
while(s.data()[size] == c)
{
if(size == 0)
return {};
size--;
}
return {s.data(), size + 1};
}
constexpr std::string_view rtrim(std::string_view s, std::initializer_list<char> c)
{
if(s.empty())
return {};
size_t size = s.size() - 1;
while(std::any_of(c.begin(), c.end(), [c1=s.data()[size]](char c2) { return c1 == c2; }))
{
if(size == 0)
return {};