pax_global_header 0000666 0000000 0000000 00000000064 14751611131 0014512 g ustar 00root root 0000000 0000000 52 comment=6738a45aaf7e285129a3f7b47c0c4dff3898c4f7
railcontrol-23+dfsg1/ 0000775 0000000 0000000 00000000000 14751611131 0014630 5 ustar 00root root 0000000 0000000 railcontrol-23+dfsg1/.cproject 0000664 0000000 0000000 00000016531 14751611131 0016450 0 ustar 00root root 0000000 0000000
make
all
true
true
true
railcontrol-23+dfsg1/.gitignore 0000664 0000000 0000000 00000000544 14751611131 0016623 0 ustar 00root root 0000000 0000000 railcontrol
railcontrol.conf
railcontrol.exe
railcontrol.sqlite
railcontrol.sqlite-journal
railcontrol.sqlite.*
railcontrol.log
railcontrol.log.*
*.tar.xz
*.zip
Storage/sqlite/sqlite3
*.o
*.so
*.bak
test/testloco
tools/Cc-Schnitte-Sniffer
gmon.out
amalgamation.cpp
.*.swp
svg/*
Version.cpp
.settings/
CMakeCache.txt
CMakeFiles/*
cmake_install.cmake
.idea/
railcontrol-23+dfsg1/.project 0000664 0000000 0000000 00000001454 14751611131 0016303 0 ustar 00root root 0000000 0000000
RailControl
org.eclipse.cdt.managedbuilder.core.genmakebuilder
clean,full,incremental,
org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
full,incremental,
org.eclipse.cdt.core.cnature
org.eclipse.cdt.core.ccnature
org.eclipse.cdt.managedbuilder.core.managedBuildNature
org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
railcontrol-23+dfsg1/ArgumentHandler.cpp 0000664 0000000 0000000 00000003456 14751611131 0020424 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include "ArgumentHandler.h"
#include "Utils/Utils.h"
ArgumentHandler::ArgumentHandler(const int argc, char* argv[], const std::map& linkMap, const char defaultSwitch)
{
for (int i = 1; i < argc; ++i)
{
char* arg = argv[i];
if (arg[0] != '-')
{
argumentMap[defaultSwitch] = arg;
continue;
}
if (arg[1] != '-')
{
argumentMap[arg[1]] = "";
continue;
}
std::string argString = arg + 2;
std::deque parts;
Utils::Utils::SplitString(argString, "=", parts);
if (parts.size() < 1)
{
continue;
}
std::string& argumentLong = parts[0];
if (linkMap.count(argumentLong) == 0)
{
std::cout << "Unknown argument " << argumentLong << std::endl;
continue;
}
char argumentShort = linkMap.at(argumentLong);
argumentMap[argumentShort] = (parts.size() == 1 ? "" : parts[1]);
}
}
std::string ArgumentHandler::GetArgumentString(const char argument, const std::string& defaultValue)
{
if (GetArgumentBool(argument) == false)
{
return defaultValue;
}
return argumentMap.at(argument);
}
railcontrol-23+dfsg1/ArgumentHandler.h 0000664 0000000 0000000 00000002630 14751611131 0020062 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "Utils/Utils.h"
class ArgumentHandler
{
public:
ArgumentHandler() = delete;
ArgumentHandler(const int argc, char* argv[], const std::map& linkMap, const char defaultSwitch);
inline bool GetArgumentBool(const char argument)
{
return (argumentMap.count(argument) == 1);
}
std::string GetArgumentString(const char argument, const std::string& defaultValue = "");
inline int GetArgumentInt(const char argument, const int defaultValue = 0)
{
return Utils::Utils::StringToInteger(GetArgumentString(argument, std::to_string(defaultValue)));
}
private:
std::map argumentMap;
};
railcontrol-23+dfsg1/CMakeLists.txt 0000664 0000000 0000000 00000020557 14751611131 0017401 0 ustar 00root root 0000000 0000000 cmake_minimum_required(VERSION 3.1)
set(RAILCONTROL_VERSION "23")
project(CMakeTest)
add_executable(railcontrol
Storage/sqlite/sqlite3.c
Storage/sqlite/sqlite3.h
Storage/sqlite/sqlite3ext.h
Manager.cpp
Manager.h
Server/Web/WebClient.cpp
Server/Web/WebClient.h
ArgumentHandler.cpp
ArgumentHandler.h
Config.cpp
Config.h
ControlInterface.h
DataModel/Accessory.cpp
DataModel/Accessory.h
DataModel/AccessoryBase.cpp
DataModel/AccessoryBase.h
DataModel/AccessoryConfig.h
DataModel/Cluster.cpp
DataModel/Cluster.h
DataModel/DataModel.h
DataModel/Feedback.cpp
DataModel/Feedback.h
DataModel/FeedbackConfig.h
DataModel/HardwareHandle.cpp
DataModel/HardwareHandle.h
DataModel/Layer.h
DataModel/LayoutItem.cpp
DataModel/LayoutItem.h
DataModel/LockableItem.cpp
DataModel/LockableItem.h
DataModel/Loco.cpp
DataModel/Loco.h
DataModel/LocoBase.cpp
DataModel/LocoBase.h
DataModel/LocoConfig.h
DataModel/LocoFunctions.cpp
DataModel/LocoFunctions.h
DataModel/MultipleUnit.cpp
DataModel/MultipleUnit.h
DataModel/Object.cpp
DataModel/Object.h
DataModel/ObjectIdentifier.cpp
DataModel/ObjectIdentifier.h
DataModel/Relation.cpp
DataModel/Relation.h
DataModel/Route.cpp
DataModel/Route.h
DataModel/Serializable.cpp
DataModel/Serializable.h
DataModel/Signal.cpp
DataModel/Signal.h
DataModel/Switch.cpp
DataModel/Switch.h
DataModel/Text.cpp
DataModel/Text.h
DataModel/Track.cpp
DataModel/Track.h
DataTypes.h
Fallthrough.h
Hardware/AccessoryCache.cpp
Hardware/AccessoryCache.h
Hardware/CS1.h
Hardware/CS2Tcp.cpp
Hardware/CS2Tcp.h
Hardware/CS2Udp.cpp
Hardware/CS2Udp.h
Hardware/Capabilities.h
Hardware/CcSchnitte.cpp
Hardware/CcSchnitte.h
Hardware/DR5000.h
Hardware/DccPpExSerial.cpp
Hardware/DccPpExSerial.h
Hardware/DccPpExTcp.cpp
Hardware/DccPpExTcp.h
Hardware/Ecos.h
Hardware/FeedbackCache.cpp
Hardware/FeedbackCache.h
Hardware/HardwareHandler.cpp
Hardware/HardwareHandler.h
Hardware/HardwareInterface.h
Hardware/HardwareParams.h
Hardware/Hsi88.cpp
Hardware/Hsi88.h
Hardware/Intellibox.h
Hardware/Intellibox2.h
Hardware/LocoCache.cpp
Hardware/LocoCache.h
Hardware/LocoNetAdapter63120.h
Hardware/LocoNetAdapter63820.h
Hardware/M6051.cpp
Hardware/M6051.h
Hardware/MasterControl.h
Hardware/MasterControl2.h
Hardware/OpenDcc.h
Hardware/Protocols/DccPpEx.cpp
Hardware/Protocols/DccPpEx.h
Hardware/Protocols/EsuCAN.cpp
Hardware/Protocols/EsuCAN.h
Hardware/Protocols/LocoNet.cpp
Hardware/Protocols/LocoNet.h
Hardware/Protocols/LocoNetLocoCache.h
Hardware/Protocols/MaerklinCAN.cpp
Hardware/Protocols/MaerklinCAN.h
Hardware/Protocols/P50x.cpp
Hardware/Protocols/P50x.h
Hardware/Protocols/P50xCache.h
Hardware/Protocols/P50xEthernet.h
Hardware/Protocols/P50xSerial.h
Hardware/Protocols/P50xUhlenbrock.h
Hardware/Protocols/Z21.cpp
Hardware/Protocols/Z21.h
Hardware/Protocols/Z21FeedbackCache.h
Hardware/Protocols/Z21LocoCache.h
Hardware/Protocols/Z21TurnoutCache.h
Hardware/RedBox.h
Hardware/Rektor.h
Hardware/TwinCenter.h
Hardware/Virtual.cpp
Hardware/Virtual.h
Hardware/Z21.h
Hardware/ZLib.cpp
Hardware/ZLib.h
Languages.cpp
Languages.h
Logger/Logger.cpp
Logger/Logger.h
Logger/LoggerClient.h
Logger/LoggerClientConsole.h
Logger/LoggerClientFile.h
Logger/LoggerClientTcp.h
Logger/LoggerServer.cpp
Logger/LoggerServer.h
Network/Select.h
Network/Serial.cpp
Network/Serial.h
Network/TcpClient.cpp
Network/TcpClient.h
Network/TcpConnection.cpp
Network/TcpConnection.h
Network/TcpServer.cpp
Network/TcpServer.h
Network/UdpClient.h
Network/UdpConnection.cpp
Network/UdpConnection.h
Network/UdpServer.cpp
Network/UdpServer.h
RailControl.cpp
RailControl.h
Server/Web/HtmlTag.cpp
Server/Web/HtmlTag.h
Server/Web/HtmlTagAccessory.cpp
Server/Web/HtmlTagAccessory.h
Server/Web/HtmlTagButton.cpp
Server/Web/HtmlTagButton.h
Server/Web/HtmlTagButtonCancel.h
Server/Web/HtmlTagButtonCommand.cpp
Server/Web/HtmlTagButtonCommand.h
Server/Web/HtmlTagButtonCommandFullScreen.cpp
Server/Web/HtmlTagButtonCommandFullScreen.h
Server/Web/HtmlTagButtonCommandPressRelease.cpp
Server/Web/HtmlTagButtonCommandPressRelease.h
Server/Web/HtmlTagButtonCommandToggle.cpp
Server/Web/HtmlTagButtonCommandToggle.h
Server/Web/HtmlTagButtonCommandWide.h
Server/Web/HtmlTagButtonMinus.h
Server/Web/HtmlTagButtonOK.h
Server/Web/HtmlTagButtonPlus.h
Server/Web/HtmlTagButtonPopup.cpp
Server/Web/HtmlTagButtonPopup.h
Server/Web/HtmlTagButtonPopupWide.h
Server/Web/HtmlTagFeedback.cpp
Server/Web/HtmlTagFeedback.h
Server/Web/HtmlTagInput.cpp
Server/Web/HtmlTagInput.h
Server/Web/HtmlTagInputCheckbox.h
Server/Web/HtmlTagInputCheckboxWithLabel.h
Server/Web/HtmlTagInputHidden.h
Server/Web/HtmlTagInputInteger.cpp
Server/Web/HtmlTagInputInteger.h
Server/Web/HtmlTagInputIntegerWithLabel.h
Server/Web/HtmlTagInputSlider.cpp
Server/Web/HtmlTagInputSlider.h
Server/Web/HtmlTagInputSliderLocoSpeed.cpp
Server/Web/HtmlTagInputSliderLocoSpeed.h
Server/Web/HtmlTagInputText.h
Server/Web/HtmlTagInputTextWithLabel.h
Server/Web/HtmlTagLabel.h
Server/Web/HtmlTagLayoutItem.cpp
Server/Web/HtmlTagLayoutItem.h
Server/Web/HtmlTagRoute.cpp
Server/Web/HtmlTagRoute.h
Server/Web/HtmlTagSelect.cpp
Server/Web/HtmlTagSelect.h
Server/Web/HtmlTagSelectMultiple.cpp
Server/Web/HtmlTagSelectMultiple.h
Server/Web/HtmlTagSelectMultipleWithLabel.cpp
Server/Web/HtmlTagSelectMultipleWithLabel.h
Server/Web/HtmlTagSelectOrientation.h
Server/Web/HtmlTagSelectOrientationWithLabel.h
Server/Web/HtmlTagSelectWithLabel.cpp
Server/Web/HtmlTagSelectWithLabel.h
Server/Web/HtmlTagSignal.cpp
Server/Web/HtmlTagSignal.h
Server/Web/HtmlTagSwitch.cpp
Server/Web/HtmlTagSwitch.h
Server/Web/HtmlTagText.cpp
Server/Web/HtmlTagText.h
Server/Web/HtmlTagTrack.cpp
Server/Web/HtmlTagTrack.h
Server/Web/Response.cpp
Server/Web/Response.h
Server/Web/ResponseCsv.cpp
Server/Web/ResponseCsv.h
Server/Web/ResponseHtml.cpp
Server/Web/ResponseHtml.h
Server/Web/ResponseHtmlFull.cpp
Server/Web/ResponseHtmlFull.h
Server/Web/ResponseHtmlNotFound.cpp
Server/Web/ResponseHtmlNotFound.h
Server/Web/ResponseHtmlNotImplemented.cpp
Server/Web/ResponseHtmlNotImplemented.h
Server/Web/WebClientCluster.cpp
Server/Web/WebClientCluster.h
Server/Web/WebClientRoute.cpp
Server/Web/WebClientRoute.h
Server/Web/WebClientSignal.cpp
Server/Web/WebClientSignal.h
Server/Web/WebClientStatic.cpp
Server/Web/WebClientStatic.h
Server/Web/WebClientText.cpp
Server/Web/WebClientText.h
Server/Web/WebClientTrack.cpp
Server/Web/WebClientTrack.h
Server/Web/WebServer.cpp
Server/Web/WebServer.h
Server/Z21/Z21Client.cpp
Server/Z21/Z21Client.h
Server/Z21/Z21Server.cpp
Server/Z21/Z21Server.h
Storage/Sqlite.cpp
Storage/Sqlite.h
Storage/StorageHandler.cpp
Storage/StorageHandler.h
Storage/StorageInterface.h
Storage/StorageParams.h
Storage/TransactionGuard.cpp
Storage/TransactionGuard.h
Utils/Network.cpp
Utils/Network.h
Utils/ThreadSafeQueue.h
Utils/Utils.cpp
Utils/Utils.h
Version.cpp
Version.cpp.dummy
Version.cpp.in
Version.h
Hardware/zlib/adler32.c
Hardware/zlib/compress.c
Hardware/zlib/crc32.c
Hardware/zlib/crc32.h
Hardware/zlib/deflate.c
Hardware/zlib/deflate.h
Hardware/zlib/gzclose.c
Hardware/zlib/gzguts.h
Hardware/zlib/gzlib.c
Hardware/zlib/gzread.c
Hardware/zlib/gzwrite.c
Hardware/zlib/infback.c
Hardware/zlib/inffast.c
Hardware/zlib/inffast.h
Hardware/zlib/inffixed.h
Hardware/zlib/inflate.c
Hardware/zlib/inflate.h
Hardware/zlib/inftrees.c
Hardware/zlib/inftrees.h
Hardware/zlib/trees.c
Hardware/zlib/trees.h
Hardware/zlib/uncompr.c
Hardware/zlib/zconf.h
Hardware/zlib/zlib.h
Hardware/zlib/zutil.c
Hardware/zlib/zutil.h
)
set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS_DEBUG "-O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS "-g -Wall -Wextra -pedantic -Werror")
set(CMAKE_C_FLAGS "-g -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_RTREE -DHAVE_USLEEP -Wno-implicit-function-declaration -Wno-return-local-addr")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(railcontrol PRIVATE Threads::Threads dl)
target_include_directories(railcontrol PRIVATE .)
add_custom_command(OUTPUT Version.cpp Version.cpp.dummy
DEPENDS Version.cpp.in
COMMAND git status -s| wc -l > ${CMAKE_CURRENT_SOURCE_DIR}/git_dirty.txt
COMMAND sed s/@COMPILE_TIMESTAMP@/`date +%s`/ < ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp.in | sed s/@GIT_HASH@/`git log -1 --format=%H`/ | sed s/@GIT_TIMESTAMP@/`git log -1 --format=%at`/ | sed s,@GIT_DIRTY@,`cat ${CMAKE_CURRENT_SOURCE_DIR}/git_dirty.txt`, | sed s/@RAILCONTROL_VERSION@/${RAILCONTROL_VERSION}/ > ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp
COMMAND rm ${CMAKE_CURRENT_SOURCE_DIR}/git_dirty.txt
COMMENT "Creating Version.cpp")
railcontrol-23+dfsg1/Config.cpp 0000664 0000000 0000000 00000004536 14751611131 0016551 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include // std::ws
#include
#include "Config.h"
#include "Logger/Logger.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
Config::Config(const std::string& fileName)
{
Logger::Logger* logger = Logger::LoggerServer::Instance().GetLogger("Config");
// read config values
logger->Info(Languages::TextReadingConfigFile, fileName);
std::ifstream configFile;
configFile.open(fileName);
if (!configFile.is_open())
{
logger->Warning(Languages::TextUnableToOpenFile, fileName);
return;
}
for (string line; std::getline(configFile, line); )
{
std::istringstream iss(line);
string configKey;
string eq;
string configValue;
iss >> configKey >> eq >> configValue >> std::ws;
if ((configKey.size() == 0) || (configKey[0] == '#'))
{
continue;
}
if (eq.compare("=") != 0)
{
continue;
}
config[configKey] = configValue;
logger->Info(Languages::TextParameterFoundInConfigFile, configKey, configValue);
}
configFile.close();
}
const string& Config::getStringValue(const string& key, const string& defaultValue)
{
if (config.count(key) != 1)
{
return defaultValue;
}
return config[key];
}
int Config::getIntValue(const string& key, const int defaultValue)
{
if (config.count(key) != 1)
{
return defaultValue;
}
return Utils::Utils::StringToInteger(config[key], defaultValue);
}
bool Config::getBoolValue(const string& key, const bool defaultValue)
{
const string value = Utils::Utils::StringToLower(getStringValue(key, string(defaultValue ? "1" : "0")));
return ((value.compare("true") == 0) || (value.compare("on") == 0) || (value.compare("1") == 0));
}
railcontrol-23+dfsg1/Config.h 0000664 0000000 0000000 00000002162 14751611131 0016207 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
class Config
{
public:
Config(const std::string& fileName);
const std::string& getStringValue(const std::string& key, const std::string& defaultValue);
int getIntValue(const std::string& key, const int defaultValue);
bool getBoolValue(const std::string& key, const bool defaultValue);
private:
std::map config;
};
railcontrol-23+dfsg1/ControlInterface.h 0000664 0000000 0000000 00000026464 14751611131 0020256 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include
#include "DataModel/AccessoryConfig.h"
#include "DataModel/Feedback.h"
#include "DataModel/FeedbackConfig.h"
#include "DataModel/LocoConfig.h"
#include "DataModel/LocoFunctions.h"
#include "DataTypes.h"
#include "Hardware/Capabilities.h"
namespace DataModel
{
class Accessory;
class Loco;
class Signal;
class Route;
class Switch;
class Track;
}
namespace Hardware
{
class HardwareParams;
}
class ControlInterface
{
public:
inline ControlInterface(ControlType controlType)
: controlType(controlType)
{
}
virtual ~ControlInterface()
{
}
virtual void Start()
{
}
virtual void ReInit(__attribute__((unused)) const Hardware::HardwareParams* params)
{
}
virtual void Stop()
{
}
ControlType GetControlType() const
{
return controlType;
}
virtual const std::string& GetName() const = 0;
virtual const std::string& GetShortName() const
{
return GetName();
}
virtual void AccessoryDelete(__attribute__((unused)) const AccessoryID accessoryID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void AccessoryProtocols(__attribute__((unused)) std::vector& protocols) const
{
}
virtual bool AccessoryProtocolSupported(__attribute__((unused)) Protocol protocol) const
{
return false;
}
virtual void AccessorySettings(__attribute__((unused)) const AccessoryID accessoryID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void AccessoryState(__attribute__((unused)) const ControlType controlType,
__attribute__((unused)) const DataModel::Accessory* accessory)
{
}
virtual void ArgumentTypes(__attribute__((unused)) std::map& argumentTypes) const
{
}
virtual void Booster(__attribute__((unused)) const ControlType controlType,
__attribute__((unused)) const BoosterState state)
{
}
virtual Hardware::Capabilities GetCapabilities() const
{
return Hardware::CapabilityNone;
}
inline bool CanHandle(const Hardware::Capabilities capability) const
{
Hardware::Capabilities hardwareCapabilities = GetCapabilities();
return capability == (hardwareCapabilities & capability);
}
virtual void FeedbackDelete(__attribute__((unused)) const FeedbackID feedbackID,
__attribute__((unused)) const std::string& name)
{
}
virtual void FeedbackSettings(__attribute__((unused)) const FeedbackID feedbackID,
__attribute__((unused)) const std::string& name)
{
}
virtual void FeedbackState(__attribute__((unused)) const std::string& name,
__attribute__((unused)) const FeedbackID feedbackID,
__attribute__((unused)) const DataModel::Feedback::FeedbackState state)
{
}
virtual void LayerDelete(__attribute__((unused)) const LayerID layerID,
__attribute__((unused)) const std::string& name)
{
}
virtual void LayerSettings(__attribute__((unused)) const LayerID layerID,
__attribute__((unused)) const std::string& name)
{
}
virtual void LocoBaseDestinationReached(__attribute__((unused)) const DataModel::LocoBase* loco,
__attribute__((unused)) const DataModel::Route* route,
__attribute__((unused)) const DataModel::Track* track)
{
}
virtual void LocoBaseOrientation(__attribute__((unused)) const ControlType controlType,
__attribute__((unused)) const DataModel::LocoBase* loco,
__attribute__((unused)) const Orientation orientation)
{
}
virtual void LocoBaseFunction(__attribute__((unused)) const ControlType controlType,
__attribute__((unused)) const DataModel::LocoBase* loco,
__attribute__((unused)) const DataModel::LocoFunctionNr function,
__attribute__((unused)) const DataModel::LocoFunctionState on)
{
}
virtual void LocoBaseRelease(__attribute__((unused)) const DataModel::LocoBase* loco)
{
}
virtual void LocoBaseSpeed(__attribute__((unused)) const ControlType controlType,
__attribute__((unused)) const DataModel::LocoBase* loco,
__attribute__((unused)) const Speed speed)
{
}
virtual void LocoBaseStart(__attribute__((unused)) const DataModel::LocoBase* loco)
{
}
virtual void LocoBaseStop(__attribute__((unused)) const DataModel::LocoBase* loco)
{
}
virtual void LocoProtocols(__attribute__((unused)) std::vector& protocols) const
{
}
virtual bool LocoProtocolSupported(__attribute__((unused)) Protocol protocol) const
{
return false;
}
virtual void LocoDelete(__attribute__((unused)) const LocoID locoID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void LocoSettings(__attribute__((unused)) const LocoID locoID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void MultipleUnitDelete(__attribute__((unused)) const MultipleUnitID multipleUnitID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void MultipleUnitSettings(__attribute__((unused)) const MultipleUnitID multipleUnitID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void RouteDelete(__attribute__((unused)) const RouteID routeID,
__attribute__((unused)) const std::string& name)
{
}
virtual void RouteRelease(__attribute__((unused)) const RouteID routeID)
{
}
virtual void RouteSettings(__attribute__((unused)) const RouteID routeID,
__attribute__((unused)) const std::string& name)
{
}
virtual void SwitchDelete(__attribute__((unused)) const SwitchID switchID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void SwitchSettings(__attribute__((unused)) const SwitchID switchID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void SwitchState(__attribute__((unused)) const ControlType controlType,
__attribute__((unused)) const DataModel::Switch* mySwitch)
{
}
virtual void TrackDelete(__attribute__((unused)) const TrackID trackID,
__attribute__((unused)) const std::string& name)
{
}
virtual void TrackSettings(__attribute__((unused)) const TrackID trackID,
__attribute__((unused)) const std::string& name)
{
}
virtual void TrackState(__attribute__((unused)) const DataModel::Track* track)
{
}
virtual void SignalDelete(__attribute__((unused)) const SignalID signalID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void SignalSettings(__attribute__((unused)) const SignalID signalID,
__attribute__((unused)) const std::string& name,
__attribute__((unused)) const std::string& matchKey)
{
}
virtual void SignalState(__attribute__((unused)) const ControlType controlType,
__attribute__((unused)) const DataModel::Signal* signal)
{
}
virtual void ClusterDelete(__attribute__((unused)) const ClusterID clusterID,
__attribute__((unused)) const std::string& name)
{
}
virtual void ClusterSettings(__attribute__((unused)) const ClusterID clusterID,
__attribute__((unused)) const std::string& name)
{
}
virtual void TextDelete(__attribute__((unused)) const TextID textID,
__attribute__((unused)) const std::string& name)
{
}
virtual void TextSettings(__attribute__((unused)) const TextID textID,
__attribute__((unused)) const std::string& name)
{
}
virtual void LocoSpeedOrientationFunctions(const DataModel::LocoBase* loco,
const Speed speed,
const Orientation orientation,
std::vector& functions)
{
LocoBaseSpeed(ControlTypeInternal, loco, speed);
LocoBaseOrientation(ControlTypeInternal, loco, orientation);
for (const DataModel::LocoFunctionEntry& functionEntry : functions)
{
LocoBaseFunction(ControlTypeInternal, loco, functionEntry.nr, functionEntry.state);
}
}
virtual void ProgramRead(__attribute__((unused)) const ProgramMode mode,
__attribute__((unused)) const Address address, __attribute__((unused)) const CvNumber cv)
{
}
virtual void ProgramWrite(__attribute__((unused)) const ProgramMode mode,
__attribute__((unused)) const Address address, __attribute__((unused)) const CvNumber cv,
__attribute__((unused)) const CvValue value)
{
}
virtual void ProgramValue(__attribute__((unused)) const CvNumber cv,
__attribute__((unused)) const CvValue value)
{
}
virtual void AddUnmatchedLocos(__attribute__((unused)) std::map& list) const
{
}
virtual std::map GetUnmatchedLocos(__attribute__((unused)) const std::string& matchKey) const
{
std::map out;
return out;
}
virtual DataModel::LocoConfig GetLocoByMatchKey(__attribute__((unused)) const std::string& matchKey) const
{
return DataModel::LocoConfig(LocoTypeLoco);
}
virtual void AddUnmatchedMultipleUnits(__attribute__((unused)) std::map& list) const
{
}
virtual std::map GetUnmatchedMultipleUnits(__attribute__((unused)) const std::string& matchKey) const
{
std::map out;
return out;
}
virtual DataModel::LocoConfig GetMultipleUnitByMatchKey(__attribute__((unused)) const std::string& matchKey) const
{
return DataModel::LocoConfig(LocoTypeMultipleUnit);
}
virtual void AddUnmatchedAccessories(__attribute__((unused)) std::map& list) const
{
}
virtual std::map GetUnmatchedAccessories(__attribute__((unused)) const std::string& matchKey) const
{
std::map out;
return out;
}
virtual DataModel::AccessoryConfig GetAccessoryByMatchKey(__attribute__((unused)) const std::string& matchKey) const
{
return DataModel::AccessoryConfig();
}
virtual void AddUnmatchedFeedbacks(__attribute__((unused)) std::map& list) const
{
}
virtual std::map GetUnmatchedFeedbacks(__attribute__((unused)) const std::string& matchKey) const
{
std::map out;
return out;
}
virtual DataModel::FeedbackConfig GetFeedbackByMatchKey(__attribute__((unused)) const std::string& matchKey) const
{
return DataModel::FeedbackConfig();
}
private:
ControlType controlType;
};
railcontrol-23+dfsg1/DataModel/ 0000775 0000000 0000000 00000000000 14751611131 0016462 5 ustar 00root root 0000000 0000000 railcontrol-23+dfsg1/DataModel/Accessory.cpp 0000664 0000000 0000000 00000003601 14751611131 0021121 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include "DataModel/Accessory.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
namespace DataModel
{
std::string Accessory::Serialize() const
{
string str = "objectType=Accessory;";
str += AccessoryBase::Serialize();
str += ";" + LayoutItem::Serialize();
str += ";" + LockableItem::Serialize();
return str;
}
bool Accessory::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
string objectType = Utils::Utils::GetStringMapEntry(arguments, "objectType");
if (objectType.compare("Accessory") != 0)
{
return false;
}
AccessoryBase::Deserialize(arguments);
LayoutItem::Deserialize(arguments);
LockableItem::Deserialize(arguments);
SetWidth(Width1);
SetHeight(Height1);
SetVisible(VisibleYes);
return true;
}
Accessory& Accessory::operator=(const Hardware::AccessoryCacheEntry& accessory)
{
SetControlID(accessory.GetControlID());
SetName(accessory.GetName());
SetAddress(accessory.GetAddress());
SetProtocol(accessory.GetProtocol());
SetMatchKey(accessory.GetMatchKey());
return *this;
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Accessory.h 0000664 0000000 0000000 00000004102 14751611131 0020563 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include "DataTypes.h"
#include "DataModel/AccessoryBase.h"
#include "DataModel/HardwareHandle.h"
#include "DataModel/LayoutItem.h"
#include "DataModel/LockableItem.h"
#include "Languages.h"
class Manager;
namespace DataModel
{
class Accessory : public AccessoryBase, public LayoutItem, public LockableItem
{
Accessory() = delete;
Accessory(const Accessory&) = delete;
Accessory& operator=(const Accessory&) = delete;
public:
inline Accessory(const AccessoryID accessoryID)
: AccessoryBase(),
LayoutItem(accessoryID),
LockableItem()
{
}
inline Accessory(__attribute__((unused)) Manager* manager, const AccessoryID accessoryID)
: Accessory(accessoryID)
{
}
inline Accessory(const std::string& serialized)
: Accessory(AccessoryNone)
{
Deserialize(serialized);
}
virtual ~Accessory()
{
}
virtual ObjectType GetObjectType() const override
{
return ObjectTypeAccessory;
}
virtual std::string GetLayoutType() const override
{
return Languages::GetText(Languages::TextAccessory);
}
virtual std::string Serialize() const override;
using HardwareHandle::Deserialize;
virtual bool Deserialize(const std::string& serialized) override;
Accessory& operator=(const Hardware::AccessoryCacheEntry& accessory);
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/AccessoryBase.cpp 0000664 0000000 0000000 00000004632 14751611131 0021721 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include "DataModel/AccessoryBase.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
namespace DataModel
{
std::string AccessoryBase::Serialize() const
{
string str = HardwareHandle::Serialize();
str += ";type=" + std::to_string(accessoryType);
str += ";state=" + std::to_string(accessoryState);
str += ";duration=" + std::to_string(duration);
str += ";inverted=" + std::to_string(inverted);
str += ";lastused=" + std::to_string(lastUsed);
str += ";counter=" + std::to_string(counter);
str += ";matchkey=" + matchKey;
return str;
}
bool AccessoryBase::Deserialize(const map& arguments)
{
HardwareHandle::Deserialize(arguments);
accessoryType = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "type"));
accessoryState = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "state", AccessoryStateOff));
duration = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "duration", DefaultAccessoryPulseDuration));
inverted = Utils::Utils::GetBoolMapEntry(arguments, "inverted");
lastUsed = Utils::Utils::GetIntegerMapEntry(arguments, "lastused", 0);
counter = Utils::Utils::GetIntegerMapEntry(arguments, "counter", 0);
matchKey = Utils::Utils::GetStringMapEntry(arguments, "matchkey");
return true;
}
AccessoryState AccessoryBase::CalculateInvertedAccessoryState(const AccessoryState state) const
{
if (inverted == false)
{
return state;
}
switch(state)
{
case AccessoryStateOff:
return AccessoryStateOn;
case AccessoryStateOn:
return AccessoryStateOff;
default:
return state;
}
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/AccessoryBase.h 0000664 0000000 0000000 00000010702 14751611131 0021361 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include
#include "DataModel/HardwareHandle.h"
#include "Hardware/AccessoryCache.h"
namespace DataModel
{
enum AccessoryType : unsigned char
{
AccessoryTypeDefault = 0,
SignalTypeSimpleLeft = 0,
SignalTypeSimpleRight = 1,
SignalTypeChDwarf = 10,
SignalTypeChLMain = 11,
SignalTypeChLDistant = 12,
SignalTypeChLCombined = 13,
SignalTypeChNMain = 14,
SignalTypeChNDistant = 15,
SignalTypeDeCombined = 20,
SwitchTypeLeft = 0,
SwitchTypeRight = 1,
SwitchTypeThreeWay = 2,
SwitchTypeMaerklinLeft = 3,
SwitchTypeMaerklinRight = 4
};
enum AccessoryState : unsigned char
{
DefaultState = 0,
AccessoryStateOff = 0,
AccessoryStateOn = 1,
SignalStateStop = 0,
SignalStateClear,
SignalStateAspect2,
SignalStateAspect3,
SignalStateAspect4,
SignalStateAspect5,
SignalStateAspect6,
SignalStateAspect7,
SignalStateAspect8,
SignalStateAspect9,
SignalStateAspect10,
SignalStateDark = 0x1F,
SignalStateStopExpected = SignalStateStop + 0x20,
SignalStateClearExpected,
SignalStateAspect2Expected,
SignalStateAspect3Expected,
SignalStateAspect4Expected,
SignalStateAspect5Expected,
SignalStateAspect6Expected,
SignalStateAspect7Expected,
SignalStateAspect8Expected,
SignalStateAspect9Expected,
SignalStateAspect10Expected,
SignalStateMax = SignalStateAspect10Expected,
SwitchStateTurnout = 0,
SwitchStateStraight = 1,
SwitchStateThird = 2,
};
typedef signed char AddressOffset;
typedef unsigned short AccessoryPulseDuration;
static const AccessoryPulseDuration DefaultAccessoryPulseDuration = 100;
class AccessoryBase : public HardwareHandle
{
public:
AccessoryBase()
: HardwareHandle(),
accessoryType(AccessoryTypeDefault),
accessoryState(AccessoryStateOff),
duration(0),
inverted(false),
lastUsed(0),
counter(0),
matchKey("")
{
}
virtual ~AccessoryBase() {}
inline AccessoryType GetType() const
{
return accessoryType;
}
virtual inline void SetType(AccessoryType type)
{
this->accessoryType = type;
}
inline AccessoryState GetAccessoryState() const
{
return accessoryState;
}
AccessoryState CalculateInvertedAccessoryState(const AccessoryState state) const;
inline AccessoryState GetInvertedAccessoryState() const
{
return CalculateInvertedAccessoryState(accessoryState);
}
inline void SetAccessoryState(const AccessoryState state)
{
this->accessoryState = state;
lastUsed = std::time(nullptr);
++counter;
}
inline AccessoryPulseDuration GetAccessoryPulseDuration() const
{
return duration;
}
inline void SetAccessoryPulseDuration(const AccessoryPulseDuration duration)
{
this->duration = duration;
}
inline bool GetInverted() const
{
return inverted;
}
inline void SetInverted(const bool inverted)
{
this->inverted = inverted;
}
inline time_t GetLastUsed() const
{
return lastUsed;
}
inline void SetMatchKey(const std::string& matchKey)
{
this->matchKey = matchKey;
}
inline void ClearMatchKey()
{
matchKey.clear();
}
inline std::string GetMatchKey() const
{
return matchKey;
}
protected:
virtual std::string Serialize() const;
virtual bool Deserialize(const std::map& arguments);
private:
AccessoryType accessoryType;
AccessoryState accessoryState;
AccessoryPulseDuration duration; // duration in ms after which the accessory command will be turned off on rails. 0 = no turn off / turn off must be made manually
bool inverted;
time_t lastUsed;
unsigned int counter;
std::string matchKey;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/AccessoryConfig.h 0000664 0000000 0000000 00000011266 14751611131 0021722 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include "DataModel/Accessory.h"
#include "DataModel/Signal.h"
#include "DataModel/Switch.h"
#include "Hardware/AccessoryCache.h"
namespace DataModel
{
class AccessoryConfig
{
public:
inline AccessoryConfig()
: controlId(ControlNone),
address(AddressDefault),
protocol(ProtocolNone),
isInUse(false)
{
}
inline AccessoryConfig(const DataModel::Accessory& accessory)
: controlId(accessory.GetControlID()),
objectIdentifier(ObjectTypeAccessory, accessory.GetID()),
address(accessory.GetAddress()),
protocol(accessory.GetProtocol()),
name(accessory.GetName()),
matchKey(accessory.GetMatchKey()),
isInUse(accessory.IsInUse())
{
}
inline AccessoryConfig(const DataModel::Signal& signal)
: controlId(signal.GetControlID()),
objectIdentifier(ObjectTypeSignal, signal.GetID()),
address(signal.GetAddress()),
protocol(signal.GetProtocol()),
name(signal.GetName()),
matchKey(signal.GetMatchKey()),
isInUse(signal.IsInUse())
{
}
inline AccessoryConfig(const DataModel::Switch& mySwitch)
: controlId(mySwitch.GetControlID()),
objectIdentifier(ObjectTypeSwitch, mySwitch.GetID()),
address(mySwitch.GetAddress()),
protocol(mySwitch.GetProtocol()),
name(mySwitch.GetName()),
matchKey(mySwitch.GetMatchKey()),
isInUse(mySwitch.IsInUse())
{
}
inline AccessoryConfig(const Hardware::AccessoryCacheEntry& entry)
: controlId(entry.GetControlID()),
objectIdentifier(entry.GetObjectIdentifier()),
address(entry.GetAddress()),
protocol(entry.GetProtocol()),
name(entry.GetName()),
matchKey(entry.GetMatchKey()),
isInUse(false)
{
}
inline AccessoryConfig& operator=(const DataModel::Accessory& accessory)
{
controlId = accessory.GetControlID();
objectIdentifier = ObjectIdentifier(ObjectTypeAccessory, accessory.GetID());
address = accessory.GetAddress();
protocol = accessory.GetProtocol();
name = accessory.GetName();
matchKey = accessory.GetMatchKey();
isInUse = accessory.IsInUse();
return *this;
}
inline AccessoryConfig& operator=(const DataModel::Signal& signal)
{
controlId = signal.GetControlID();
objectIdentifier = ObjectIdentifier(ObjectTypeSignal, signal.GetID());
address = signal.GetAddress();
protocol = signal.GetProtocol();
name = signal.GetName();
matchKey = signal.GetMatchKey();
isInUse = signal.IsInUse();
return *this;
}
inline AccessoryConfig& operator=(const DataModel::Switch& accessory)
{
controlId = accessory.GetControlID();
objectIdentifier = ObjectIdentifier(ObjectTypeSwitch, accessory.GetID());
address = accessory.GetAddress();
protocol = accessory.GetProtocol();
name = accessory.GetName();
matchKey = accessory.GetMatchKey();
isInUse = accessory.IsInUse();
return *this;
}
inline AccessoryConfig& operator=(const Hardware::AccessoryCacheEntry& entry)
{
controlId = entry.GetControlID();
objectIdentifier = entry.GetObjectIdentifier();
address = entry.GetAddress();
protocol = entry.GetProtocol();
name = entry.GetName();
matchKey = entry.GetMatchKey();
return *this;
}
inline ControlID GetControlId() const
{
return controlId;
}
inline ObjectIdentifier GetObjectIdentifier() const
{
return objectIdentifier;
}
inline Address GetAddress() const
{
return address;
}
inline Protocol GetProtocol() const
{
return protocol;
}
inline std::string GetName() const
{
return name;
}
inline void SetName(const std::string& name)
{
this->name = name;
}
inline std::string GetMatchKey() const
{
return matchKey;
}
inline bool IsInUse() const
{
return isInUse;
}
private:
ControlID controlId;
ObjectIdentifier objectIdentifier;
Address address;
Protocol protocol;
std::string name;
std::string matchKey;
bool isInUse;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Cluster.cpp 0000664 0000000 0000000 00000007411 14751611131 0020612 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include "DataModel/Cluster.h"
#include "DataModel/LockableItem.h"
#include "DataModel/Relation.h"
#include "DataModel/Signal.h"
#include "DataModel/Track.h"
#include "Manager.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
using std::to_string;
namespace DataModel
{
std::string Cluster::Serialize() const
{
string str;
str += "objectType=Cluster;";
str += Object::Serialize();
str += ";orientation=";
str += to_string(orientation);
return str;
}
bool Cluster::Deserialize(const string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
Object::Deserialize(arguments);
if (!arguments.count("objectType") || arguments.at("objectType").compare("Cluster") != 0)
{
return false;
}
orientation = static_cast(Utils::Utils::GetBoolMapEntry(arguments, "orientation", OrientationRight));
return true;
}
bool Cluster::CanSetLocoBaseOrientation(const Orientation orientation, const ObjectIdentifier& locoBaseIdentifier)
{
std::lock_guard Guard(orientationMutex);
if (this->orientation == orientation)
{
return true;
}
for (auto relation : tracks)
{
Track* track = dynamic_cast(relation->GetObject2());
if (track == nullptr)
{
return false;
}
if (track->GetLockState() == DataModel::LockableItem::LockStateFree)
{
continue;
}
if (track->GetLocoBase() == locoBaseIdentifier)
{
continue;
}
return false;
}
return true;
}
bool Cluster::SetLocoBaseOrientation(const Orientation orientation, const ObjectIdentifier& locoBaseIdentifier)
{
std::lock_guard Guard(orientationMutex);
if (this->orientation == orientation)
{
return true;
}
for (auto relation : tracks)
{
Track* track = dynamic_cast(relation->GetObject2());
if (track == nullptr)
{
return false;
}
if (track->GetLockState() == DataModel::LockableItem::LockStateFree)
{
continue;
}
if (track->GetLocoBase() == locoBaseIdentifier)
{
continue;
}
return false;
}
this->orientation = orientation;
return true;
}
void Cluster::DeleteTracks()
{
while (tracks.size() > 0)
{
Relation* trackRelation = tracks.back();
Track* track = dynamic_cast(trackRelation->GetObject2());
if (track != nullptr)
{
track->SetCluster(nullptr);
}
tracks.pop_back();
delete trackRelation;
}
}
void Cluster::DeleteTrack(Track* trackToDelete)
{
for (unsigned int index = 0; index < tracks.size(); ++index)
{
if (tracks[index]->GetObject2() != trackToDelete)
{
continue;
}
delete tracks[index];
tracks.erase(tracks.begin() + index);
trackToDelete->SetCluster(nullptr);
return;
}
}
void Cluster::AssignTracks(const std::vector& newTracks)
{
DeleteTracks();
tracks = newTracks;
for (auto trackRelation : tracks)
{
Track* track = dynamic_cast(trackRelation->GetObject2());
if (track != nullptr)
{
track->SetCluster(this);
}
}
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Cluster.h 0000664 0000000 0000000 00000004274 14751611131 0020263 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include
#include "DataTypes.h"
#include "DataModel/Object.h"
class Manager;
namespace DataModel
{
class Relation;
class Signal;
class Track;
class Cluster : public Object
{
public:
Cluster(__attribute__((unused)) Manager* manager, const ClusterID clusterID)
: Object(clusterID),
orientation(OrientationRight)
{
}
Cluster(const std::string& serialized)
: Object(ClusterNone),
orientation(OrientationRight)
{
Deserialize(serialized);
}
virtual ~Cluster()
{
DeleteTracks();
}
inline ObjectType GetObjectType() const override
{
return ObjectTypeCluster;
}
std::string Serialize() const override;
bool Deserialize(const std::string& serialized) override;
bool CanSetLocoBaseOrientation(const Orientation orientation, const ObjectIdentifier& locoBaseIdentifier);
bool SetLocoBaseOrientation(const Orientation orientation, const ObjectIdentifier& locoBaseIdentifier);
inline Orientation GetLocoOrientation() const
{
return orientation;
}
inline const std::vector& GetTracks() const
{
return tracks;
}
void DeleteTracks();
void DeleteTrack(DataModel::Track* trackToDelete);
void AssignTracks(const std::vector& newTracks);
private:
Orientation orientation;
mutable std::mutex orientationMutex;
std::vector tracks;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/DataModel.h 0000664 0000000 0000000 00000002357 14751611131 0020474 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include "DataModel/Accessory.h"
#include "DataModel/AccessoryBase.h"
#include "DataModel/Cluster.h"
#include "DataModel/Feedback.h"
#include "DataModel/Layer.h"
#include "DataModel/Loco.h"
#include "DataModel/LocoBase.h"
#include "DataModel/LocoFunctions.h"
#include "DataModel/MultipleUnit.h"
#include "DataModel/ObjectIdentifier.h"
#include "DataModel/Relation.h"
#include "DataModel/Route.h"
#include "DataModel/Signal.h"
#include "DataModel/Switch.h"
#include "DataModel/Text.h"
#include "DataModel/Track.h"
railcontrol-23+dfsg1/DataModel/Feedback.cpp 0000664 0000000 0000000 00000007121 14751611131 0020653 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include "DataModel/Feedback.h"
#include "Manager.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
using std::to_string;
namespace DataModel
{
string Feedback::Serialize() const
{
string str;
str = "objectType=Feedback;" + LayoutItem::Serialize();
str += ";controlID=" + to_string(controlID);
str += ";pin=" + to_string(pin);
str += ";inverted=" + to_string(inverted);
str += ";state=" + to_string(stateCounter > 0);
str += ";matchkey=" + matchKey;
str += ";track=" + to_string(trackID);
return str;
}
bool Feedback::Deserialize(const string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
string objectType = Utils::Utils::GetStringMapEntry(arguments, "objectType");
if (objectType.compare("Feedback") != 0)
{
return false;
}
LayoutItem::Deserialize(arguments);
SetRotation(Rotation0);
SetHeight(Height1);
SetWidth(Width1);
controlID = Utils::Utils::GetIntegerMapEntry(arguments, "controlID", ControlIdNone);
pin = Utils::Utils::GetIntegerMapEntry(arguments, "pin");
inverted = Utils::Utils::GetBoolMapEntry(arguments, "inverted", false);
stateCounter = Utils::Utils::GetBoolMapEntry(arguments, "state", FeedbackStateFree) ? MaxStateCounter : 0;
matchKey = Utils::Utils::GetStringMapEntry(arguments, "matchkey");
trackID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "track", TrackNone));
return true;
}
void Feedback::SetState(const FeedbackState newState)
{
FeedbackState state = static_cast(newState != inverted);
{
std::lock_guard Guard(updateMutex);
if (state == FeedbackStateFree)
{
if (stateCounter < MaxStateCounter)
{
return;
}
stateCounter = MaxStateCounter - 1;
return;
}
unsigned char oldStateCounter = stateCounter;
stateCounter = MaxStateCounter;
if (oldStateCounter > 0)
{
return;
}
}
manager->FeedbackPublishState(this);
UpdateTrackState(FeedbackStateOccupied);
}
void Feedback::UpdateTrack()
{
if (track != nullptr)
{
return;
}
track = manager->GetTrack(trackID);
}
void Feedback::UpdateTrackState(const FeedbackState state)
{
UpdateTrack();
if (track == nullptr)
{
return;
}
track->SetFeedbackState(GetID(), state);
}
void Feedback::Debounce()
{
{
std::lock_guard Guard(updateMutex);
if (stateCounter == MaxStateCounter || stateCounter == 0)
{
return;
}
--stateCounter;
if (stateCounter != 0)
{
return;
}
}
manager->FeedbackPublishState(this);
UpdateTrackState(FeedbackStateFree);
}
Feedback& Feedback::operator=(const Hardware::FeedbackCacheEntry& feedback)
{
SetControlID(feedback.GetControlID());
SetPin(feedback.GetPin());
SetName(feedback.GetName());
SetMatchKey(feedback.GetMatchKey());
return *this;
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Feedback.h 0000664 0000000 0000000 00000007427 14751611131 0020331 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataTypes.h"
#include "DataModel/ObjectIdentifier.h"
#include "DataModel/LayoutItem.h"
#include "Hardware/FeedbackCache.h"
#include "Languages.h"
class Manager;
namespace DataModel
{
class Track;
class Feedback : public LayoutItem
{
public:
enum FeedbackState : bool
{
FeedbackStateFree = false,
FeedbackStateOccupied = true
};
inline Feedback(Manager* manager,
const FeedbackID feedbackID)
: LayoutItem(feedbackID),
controlID(ControlIdNone),
pin(FeedbackPinNone),
manager(manager),
inverted(false),
trackID(TrackNone),
track(nullptr),
stateCounter(0)
{
}
inline Feedback(Manager* manager, const std::string& serialized)
: manager(manager),
track(nullptr)
{
Deserialize(serialized);
}
inline ObjectType GetObjectType() const override
{
return ObjectTypeFeedback;
}
std::string Serialize() const override;
bool Deserialize(const std::string& serialized) override;
inline bool IsInUse() const
{
return IsRelatedTrackSet();
}
inline std::string GetLayoutType() const override
{
return Languages::GetText(Languages::TextFeedback);
}
inline void SetInverted(const bool inverted)
{
this->inverted = inverted;
}
inline bool GetInverted() const
{
return inverted;
}
void SetState(const FeedbackState state);
inline FeedbackState GetState() const
{
return static_cast(stateCounter > 0);
}
void Debounce();
inline void SetControlID(const ControlID controlID)
{
this->controlID = controlID;
}
inline ControlID GetControlID() const
{
return controlID;
}
inline void SetPin(const FeedbackPin pin)
{
this->pin = pin;
}
inline FeedbackPin GetPin() const
{
return pin;
}
inline void ClearRelatedTrack()
{
trackID = TrackNone;
track = nullptr;
}
inline bool IsRelatedTrackSet() const
{
return trackID != TrackNone;
}
inline void SetRelatedTrack(const TrackID trackID)
{
this->trackID = trackID;
track = nullptr;
}
inline TrackID GetRelatedTrack() const
{
return trackID;
}
inline bool CompareRelatedTrack(const TrackID trackID) const
{
return this->trackID == trackID;
}
inline Track* GetTrack()
{
UpdateTrack();
return track;
}
inline void SetMatchKey(const std::string& matchKey)
{
this->matchKey = matchKey;
}
inline void ClearMatchKey()
{
matchKey.clear();
}
inline std::string GetMatchKey() const
{
return matchKey;
}
Feedback& operator=(const Hardware::FeedbackCacheEntry& feedback);
private:
void UpdateTrack();
void UpdateTrackState(const FeedbackState state);
ControlID controlID;
FeedbackPin pin;
Manager* manager;
bool inverted;
TrackID trackID;
Track* track;
unsigned char stateCounter;
static const unsigned char MaxStateCounter = 10;
mutable std::mutex updateMutex;
std::string matchKey;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/FeedbackConfig.h 0000664 0000000 0000000 00000005466 14751611131 0021460 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include "DataModel/Feedback.h"
#include "Hardware/FeedbackCache.h"
namespace DataModel
{
class FeedbackConfig
{
public:
inline FeedbackConfig()
: controlId(ControlNone),
feedbackId(FeedbackNone),
pin(FeedbackPinNone),
isInUse(false)
{
}
inline FeedbackConfig(const DataModel::Feedback& feedback)
: controlId(feedback.GetControlID()),
feedbackId(feedback.GetID()),
pin(feedback.GetPin()),
name(feedback.GetName()),
matchKey(feedback.GetMatchKey()),
isInUse(feedback.IsInUse())
{
}
inline FeedbackConfig(const Hardware::FeedbackCacheEntry& feedback)
: controlId(feedback.GetControlID()),
feedbackId(feedback.GetFeedbackID()),
pin(feedback.GetPin()),
name(feedback.GetName()),
matchKey(feedback.GetMatchKey()),
isInUse(false)
{
}
inline FeedbackConfig& operator=(const DataModel::Feedback& feedback)
{
controlId = feedback.GetControlID();
feedbackId = feedback.GetID();
pin = feedback.GetPin();
name = feedback.GetName();
matchKey = feedback.GetMatchKey();
isInUse = feedback.IsInUse();
return *this;
}
inline FeedbackConfig& operator=(const Hardware::FeedbackCacheEntry& feedback)
{
controlId = feedback.GetControlID();
feedbackId = feedback.GetFeedbackID();
pin = feedback.GetPin();
name = feedback.GetName();
matchKey = feedback.GetMatchKey();
return *this;
}
inline ControlID GetControlId() const
{
return controlId;
}
inline FeedbackID GetFeedbackId() const
{
return feedbackId;
}
inline FeedbackPin GetPin() const
{
return pin;
}
inline std::string GetName() const
{
return name;
}
inline void SetName(const std::string& name)
{
this->name = name;
}
inline std::string GetMatchKey() const
{
return matchKey;
}
inline bool IsInUse() const
{
return isInUse;
}
private:
ControlID controlId;
FeedbackID feedbackId;
FeedbackPin pin;
std::string name;
std::string matchKey;
bool isInUse;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/HardwareHandle.cpp 0000664 0000000 0000000 00000002673 14751611131 0022047 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include "DataModel/HardwareHandle.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
using std::to_string;
namespace DataModel
{
std::string HardwareHandle::Serialize() const
{
string str = "controlID=" + to_string(controlID);
str += ";protocol=" + to_string(protocol);
str += ";address=" + to_string(address);
return str;
}
bool HardwareHandle::Deserialize(const map& arguments)
{
controlID = Utils::Utils::GetIntegerMapEntry(arguments, "controlID", ControlIdNone);
protocol = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "protocol", ProtocolNone));
address = Utils::Utils::GetIntegerMapEntry(arguments, "address");
return true;
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/HardwareHandle.h 0000664 0000000 0000000 00000003606 14751611131 0021511 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataTypes.h"
#include "DataModel/Serializable.h"
namespace DataModel
{
class HardwareHandle
{
// simply stores controlID, protocol and base address of an object
// this is only to prevent copying code and use a base class instead
public:
inline HardwareHandle()
: controlID(ControlNone),
protocol(ProtocolNone),
address(AddressNone)
{
}
virtual ~HardwareHandle()
{
}
inline void SetControlID(ControlID controlID)
{
this->controlID = controlID;
}
inline ControlID GetControlID() const
{
return controlID;
}
inline void SetProtocol(Protocol protocol)
{
this->protocol = protocol;
}
inline Protocol GetProtocol() const
{
return protocol;
}
inline void SetAddress(Address address)
{
this->address = address;
}
inline Address GetAddress() const
{
return address;
}
protected:
virtual std::string Serialize() const;
virtual bool Deserialize(const std::map& arguments);
private:
ControlID controlID;
Protocol protocol;
Address address;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Layer.h 0000664 0000000 0000000 00000002470 14751611131 0017712 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataTypes.h"
#include "DataModel/Object.h"
class Manager;
namespace DataModel
{
class Layer : public Object
{
public:
Layer(const std::string& serialized)
: Object()
{
Object::Deserialize(serialized);
}
Layer(__attribute__((unused)) Manager* manager, const LayerID layerID)
: Object(layerID)
{
}
virtual std::string Serialize() const
{
return "objectType=Layer;" + Object::Serialize();
}
ObjectType GetObjectType() const
{
return ObjectTypeLayer;
}
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LayoutItem.cpp 0000664 0000000 0000000 00000007272 14751611131 0021272 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include
#include "DataModel/LayoutItem.h"
#include "Utils/Utils.h"
using std::map;
using std::stringstream;
using std::string;
namespace DataModel
{
bool LayoutItem::MapPosition(const LayoutPosition posX,
const LayoutPosition posY,
const LayoutItemSize width,
const LayoutItemSize height,
const LayoutRotation rotation,
LayoutPosition& x,
LayoutPosition& y,
LayoutItemSize& w,
LayoutItemSize& h)
{
x = posX;
y = posY;
switch (rotation)
{
case Rotation0:
case Rotation180:
w = width;
h = height;
return true;
case Rotation90:
case Rotation270:
w = height;
h = width;
return true;
default:
return false;
}
}
bool LayoutItem::CheckPositionFree(const LayoutPosition posX, const LayoutPosition posY, const LayoutPosition posZ)
{
if (this->visible == false)
{
return true;
}
if (this->posZ != posZ)
{
return true;
}
LayoutPosition x;
LayoutPosition y;
LayoutItemSize w;
LayoutItemSize h;
bool ret = MapPosition(this->posX, this->posY, this->width, this->height, this->rotation, x, y, w, h);
if (ret == false)
{
return false;
}
for (LayoutPosition ix = x; ix < x + w; ix++)
{
for (LayoutPosition iy = y; iy < y + h; iy++)
{
if (ix == posX && iy == posY)
{
return false;
}
}
}
return true;
}
std::string LayoutItem::Serialize() const
{
stringstream ss;
ss << Object::Serialize()
<< ";visible=" << static_cast(visible)
<< ";posX=" << static_cast(posX)
<< ";posY=" << static_cast(posY)
<< ";posZ=" << static_cast(posZ)
<< ";width=" << static_cast(width)
<< ";height=" << static_cast(height)
<< ";rotation=" << static_cast(rotation);
return ss.str();
}
bool LayoutItem::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
return Deserialize(arguments);
}
bool LayoutItem::Deserialize(const map& arguments)
{
Object::Deserialize(arguments);
visible = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "visible"));
if (visible > VisibleYes)
{
visible = VisibleYes;
}
posX = Utils::Utils::GetIntegerMapEntry(arguments, "posX", 0);
posY = Utils::Utils::GetIntegerMapEntry(arguments, "posY", 0);
posZ = Utils::Utils::GetIntegerMapEntry(arguments, "posZ", 0);
width = Utils::Utils::GetIntegerMapEntry(arguments, "width", Width1);
height = Utils::Utils::GetIntegerMapEntry(arguments, "height", Height1);
rotation = Utils::Utils::GetIntegerMapEntry(arguments, "rotation", Rotation0);
if (rotation > Rotation270)
{
rotation = Rotation0;
}
return true;
}
std::string LayoutItem::Rotation(LayoutRotation rotation)
{
switch (rotation)
{
case Rotation90:
return "90";
case Rotation180:
return "180";
case Rotation270:
return "270";
case Rotation0:
default:
return "0";
}
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LayoutItem.h 0000664 0000000 0000000 00000013032 14751611131 0020726 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataTypes.h"
#include "DataModel/Object.h"
namespace DataModel
{
class LayoutItem : public Object
{
public:
enum LayoutRotationEnum : unsigned char
{
Rotation0 = 0,
Rotation90,
Rotation180,
Rotation270,
RotationNotRelevant
};
class LayoutRotation
{
public:
inline LayoutRotation()
: rotation(Rotation0)
{
}
inline LayoutRotation(const LayoutRotationEnum rotation)
: rotation(rotation)
{
}
inline LayoutRotation(const int rotation)
{
*this = rotation;
}
inline LayoutRotation& operator=(const int rotation)
{
this->rotation = (rotation > RotationNotRelevant || rotation < Rotation0) ? Rotation0 : static_cast(rotation);
return *this;
}
inline LayoutRotation& operator=(const LayoutRotationEnum rotation)
{
this->rotation = rotation;
return *this;
}
inline bool operator==(const LayoutRotationEnum rotation) const
{
return this->rotation == rotation;
}
inline bool operator!=(const LayoutRotationEnum rotation) const
{
return this->rotation != rotation;
}
inline LayoutRotation& operator++()
{
unsigned char r = static_cast(rotation);
++r;
r &= 0x03;
rotation = static_cast(r);
return *this;
}
inline operator LayoutRotationEnum() const
{
return rotation;
}
private:
LayoutRotationEnum rotation;
};
typedef unsigned char LayoutItemSize;
typedef signed char LayoutPosition;
enum Visible : unsigned char
{
VisibleNo = 0,
VisibleYes,
VisibleNotRelevant
};
static const LayoutItemSize Width1 = 1;
static const LayoutItemSize Height1 = 1;
static const LayoutItemSize Height2 = 2;
inline LayoutItem(const ObjectID objectID)
: Object(objectID),
visible(VisibleYes),
posX(0),
posY(0),
posZ(0),
width(Width1),
height(Height1),
rotation(Rotation0)
{
}
inline LayoutItem()
: LayoutItem(0)
{
}
virtual ~LayoutItem() {}
static bool MapPosition(const LayoutPosition posX, const LayoutPosition posY, const LayoutItemSize width, const LayoutItemSize height, const LayoutRotation rotation, LayoutPosition& x, LayoutPosition& y, LayoutItemSize& w, LayoutItemSize& h);
virtual bool Position(LayoutPosition& x,
LayoutPosition& y,
LayoutPosition& z,
LayoutItemSize& w,
LayoutItemSize& h,
LayoutRotation& r) const
{
z = posZ;
r = rotation;
return MapPosition(posX, posY, width, height, rotation, x, y, w, h);
}
virtual bool CheckPositionFree(const LayoutPosition posX, const LayoutPosition posY, const LayoutPosition posZ);
virtual std::string Serialize() const override;
virtual bool Deserialize(const std::string& serialized) override;
virtual std::string GetLayoutType() const = 0;
inline void SetVisible(const Visible visible)
{
this->visible = visible;
}
inline Visible GetVisible() const
{
return visible;
}
inline void SetPosX(const LayoutPosition x)
{
this->posX = x;
}
inline LayoutPosition GetPosX() const
{
return posX;
}
inline void SetPosY(const LayoutPosition y)
{
this->posY = y;
}
inline LayoutPosition GetPosY() const
{
return posY;
}
inline void SetPosZ(const LayoutPosition z)
{
this->posZ = z;
}
inline LayoutPosition GetPosZ() const
{
return posZ;
}
inline bool HasPosition(const LayoutPosition x,
const LayoutPosition y,
const LayoutPosition z) const
{
return posX == x && posY == y && posZ == z;
}
inline bool IsVisibleOnLayer(const LayoutPosition z) const
{
return posZ == z && visible == VisibleYes;
}
inline void SetWidth(const LayoutItemSize width)
{
this->width = width;
}
inline LayoutItemSize GetWidth() const
{
return width;
}
inline void SetHeight(const LayoutItemSize height)
{
this->height = height;
}
inline LayoutItemSize GetHeight() const
{
return height;
}
inline void SetRotation(const LayoutRotation rotation)
{
this->rotation = rotation;
}
inline LayoutRotation GetRotation() const
{
return rotation;
}
virtual std::string Rotation() const
{
return Rotation(rotation);
}
inline void Rotate()
{
++rotation;
}
static std::string Rotation(LayoutRotation rotation);
protected:
virtual bool Deserialize(const std::map& arguments) override;
private:
Visible visible;
LayoutPosition posX;
LayoutPosition posY;
LayoutPosition posZ;
LayoutItemSize width;
LayoutItemSize height;
LayoutRotation rotation;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LockableItem.cpp 0000664 0000000 0000000 00000007370 14751611131 0021530 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include "DataModel/LockableItem.h"
#include "DataModel/Object.h"
#include "Utils/Utils.h"
using std::map;
using std::stringstream;
using std::string;
namespace DataModel
{
string LockableItem::Serialize() const
{
return "lockstate=" + std::to_string(lockState)
+ ";locobaseid=" + std::to_string(locoBaseIdentifier.GetObjectID())
+ ";locobasetype=" + std::to_string(locoBaseIdentifier.GetObjectType());
}
bool LockableItem::Deserialize(const map arguments)
{
const LocoID locoID = Utils::Utils::GetIntegerMapEntry(arguments, "locoID", LocoNone); // FIXME: Remove later: 2024-02-08
locoBaseIdentifier.SetObjectID(Utils::Utils::GetIntegerMapEntry(arguments, "locobaseid", locoID));
locoBaseIdentifier.SetObjectType(static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "locobasetype", ObjectTypeLoco)));
lockState = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "lockState", LockStateFree)); // FIXME: Remove later: 2024-02-08
lockState = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "lockstate", lockState));
return true;
}
bool LockableItem::Reserve(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier)
{
std::lock_guard Guard(lockMutex);
if (this->locoBaseIdentifier == locoBaseIdentifier)
{
if (lockState == LockStateFree)
{
lockState = LockStateReserved;
}
return true;
}
if (this->locoBaseIdentifier.IsSet())
{
Object *object = dynamic_cast(this);
if (object == nullptr)
{
return false;
}
logger->Debug(Languages::TextIsNotFree, object->GetName());
return false;
}
if (lockState != LockStateFree)
{
Object *object = dynamic_cast(this);
if (object == nullptr)
{
return false;
}
logger->Debug(Languages::TextIsNotFree, object->GetName());
return false;
}
lockState = LockStateReserved;
this->locoBaseIdentifier = locoBaseIdentifier;
return true;
}
bool LockableItem::Lock(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier)
{
std::lock_guard Guard(lockMutex);
if (this->locoBaseIdentifier != locoBaseIdentifier)
{
Object *object = dynamic_cast(this);
if (object == nullptr)
{
return false;
}
logger->Debug(Languages::TextIsNotFree, object->GetName());
return false;
}
if (lockState != LockStateReserved && lockState != LockStateHardLocked)
{
Object *object = dynamic_cast(this);
if (object == nullptr)
{
return false;
}
logger->Debug(Languages::TextIsNotFree, object->GetName());
return false;
}
lockState = LockStateHardLocked;
return true;
}
bool LockableItem::Release(__attribute__((unused)) Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier)
{
std::lock_guard Guard(lockMutex);
if (this->locoBaseIdentifier != locoBaseIdentifier && locoBaseIdentifier.IsSet())
{
return false;
}
this->locoBaseIdentifier.Clear();
lockState = LockStateFree;
return true;
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LockableItem.h 0000664 0000000 0000000 00000003630 14751611131 0021170 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataTypes.h"
#include "Logger/Logger.h"
namespace DataModel
{
class LockableItem
{
public:
enum LockState : unsigned char
{
LockStateFree = 0,
LockStateReserved,
LockStateSoftLocked,
LockStateHardLocked
};
inline LockableItem()
: lockState(LockStateFree),
locoBaseIdentifier()
{
}
virtual ~LockableItem() {};
std::string Serialize() const;
bool Deserialize(const std::map arguments);
inline ObjectIdentifier GetLocoBase() const
{
return locoBaseIdentifier;
}
inline LockState GetLockState() const
{
return lockState;
}
virtual bool Reserve(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier);
virtual bool Lock(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier);
virtual bool Release(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier);
inline bool IsInUse() const
{
return lockState != LockStateFree || locoBaseIdentifier.IsSet();
}
private:
std::mutex lockMutex;
LockState lockState;
ObjectIdentifier locoBaseIdentifier;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Loco.cpp 0000664 0000000 0000000 00000003304 14751611131 0020062 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include
#include "DataModel/Loco.h"
#include "Hardware/LocoCache.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
using std::to_string;
using std::vector;
namespace DataModel
{
std::string Loco::Serialize() const
{
string str;
str += "objectType=Loco;";
str += LocoBase::Serialize();
return str;
}
bool Loco::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
if (!arguments.count("objectType") || arguments.at("objectType").compare("Loco") != 0)
{
return false;
}
LocoBase::Deserialize(arguments);
return true;
}
Loco& Loco::operator=(const Hardware::LocoCacheEntry& loco)
{
SetControlID(loco.GetControlID());
SetAddress(loco.GetAddress());
SetProtocol(loco.GetProtocol());
SetName(loco.GetName());
SetMatchKey(loco.GetMatchKey());
ConfigureFunctions(loco.GetFunctionStates());
return *this;
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Loco.h 0000664 0000000 0000000 00000003175 14751611131 0017535 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include
#include
#include "DataTypes.h"
#include "DataModel/LocoFunctions.h"
#include "DataModel/LocoBase.h"
#include "DataModel/Relation.h"
namespace DataModel
{
class Loco : public LocoBase
{
public:
Loco() = delete;
Loco(const Loco&) = delete;
Loco& operator=(const Loco&) = delete;
inline Loco(Manager* manager, const LocoID locoID)
: LocoBase(manager, locoID)
{
}
inline Loco(Manager* manager, const std::string& serialized)
: LocoBase(manager, serialized)
{
Loco::Deserialize(serialized);
}
virtual ~Loco()
{
}
inline ObjectType GetObjectType() const override
{
return ObjectTypeLoco;
}
std::string Serialize() const override;
bool Deserialize(const std::string& serialized) override;
Loco& operator=(const Hardware::LocoCacheEntry& loco);
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LocoBase.cpp 0000664 0000000 0000000 00000054351 14751611131 0020665 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include
#include "DataModel/LocoBase.h"
#include "DataModel/Track.h"
#include "Hardware/LocoCache.h"
#include "Manager.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
using std::to_string;
using std::vector;
namespace DataModel
{
LocoBase::~LocoBase()
{
while (true)
{
{
std::lock_guard Guard(stateMutex);
if (state == LocoStateManual)
{
break;
}
}
logger->Info(Languages::TextWaitingUntilHasStopped, GetName());
Utils::Utils::SleepForSeconds(1);
}
}
std::string LocoBase::Serialize() const
{
string str;
str += Object::Serialize();
str += ";" + HardwareHandle::Serialize();
str += ";functions=" + functions.Serialize();
str += ";orientation=" + to_string(orientation);
str += ";track=" + to_string(trackFrom ? trackFrom->GetID() : TrackNone);
str += ";length=" + to_string(length);
str += ";pushpull=" + to_string(pushpull);
str += ";maxspeed=" + to_string(maxSpeed);
str += ";travelspeed=" + to_string(travelSpeed);
str += ";reducedspeed=" + to_string(reducedSpeed);
str += ";creepingspeed=" + to_string(creepingSpeed);
str += ";propulsion=" + to_string(propulsion);
str += ";type=" + to_string(trainType);
str += ";matchkey=" + matchKey;
return str;
}
bool LocoBase::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
return LocoBase::Deserialize(arguments);
}
bool LocoBase::Deserialize(const std::map& arguments)
{
Object::Deserialize(arguments);
HardwareHandle::Deserialize(arguments);
trackFrom = manager->GetTrack(static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "track", TrackNone)));
functions.Deserialize(Utils::Utils::GetStringMapEntry(arguments, "functions", "0"));
orientation = static_cast(Utils::Utils::GetBoolMapEntry(arguments, "orientation", OrientationRight));
length = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "length", 0));
pushpull = Utils::Utils::GetBoolMapEntry(arguments, "pushpull", false);
maxSpeed = Utils::Utils::GetIntegerMapEntry(arguments, "maxspeed", MaxSpeed);
travelSpeed = Utils::Utils::GetIntegerMapEntry(arguments, "travelspeed", DefaultTravelSpeed);
reducedSpeed = Utils::Utils::GetIntegerMapEntry(arguments, "reducedspeed", DefaultReducedSpeed);
creepingSpeed = Utils::Utils::GetIntegerMapEntry(arguments, "creepspeed", DefaultCreepingSpeed);
creepingSpeed = Utils::Utils::GetIntegerMapEntry(arguments, "creepingspeed", creepingSpeed);
propulsion = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "propulsion", PropulsionUnknown));
trainType = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "type", TrainTypeUnknown));
matchKey = Utils::Utils::GetStringMapEntry(arguments, "matchkey");
return true;
}
Propulsion LocoBase::GetPropulsion() const
{
return propulsion;
}
bool LocoBase::SetTrack(const TrackID trackID)
{
std::lock_guard Guard(stateMutex);
// there must not be set a track
if (this->trackFrom != nullptr)
{
return false;
}
this->trackFrom = manager->GetTrack(trackID);
return true;
}
TrackID LocoBase::GetTrackId()
{
if (trackFrom)
{
return trackFrom->GetID();
}
return TrackNone;
}
bool LocoBase::Release()
{
manager->LocoBaseSpeed(ControlTypeInternal, this, MinSpeed);
ForceManualMode();
std::lock_guard Guard(stateMutex);
if (routeFirst != nullptr)
{
routeFirst->Release(logger, GetObjectIdentifier());
routeFirst = nullptr;
}
if (routeSecond != nullptr)
{
routeSecond->Release(logger, GetObjectIdentifier());
routeSecond = nullptr;
}
if (trackFrom != nullptr)
{
trackFrom->Release(logger, GetObjectIdentifier());
trackFrom = nullptr;
}
if (trackFirst != nullptr)
{
trackFirst->Release(logger, GetObjectIdentifier());
trackFirst = nullptr;
}
if (trackSecond != nullptr)
{
trackSecond->Release(logger, GetObjectIdentifier());
trackSecond = nullptr;
}
feedbackIdOver = FeedbackNone;
feedbackIdStop = FeedbackNone;
feedbackIdCreep = FeedbackNone;
feedbackIdReduced = FeedbackNone;
feedbackIdFirst = FeedbackNone;
return true;
}
bool LocoBase::IsRunningFromTrack(const TrackID trackID) const
{
std::lock_guard Guard(stateMutex);
return trackFirst != nullptr && trackFrom != nullptr && trackFrom->GetID() == trackID;
}
bool LocoBase::GoToAutoMode(const AutoModeType type)
{
std::lock_guard Guard(stateMutex);
if (trackFrom == nullptr)
{
logger->Warning(Languages::TextCanNotStartNotOnTrack);
return false;
}
if (state == LocoStateError)
{
logger->Warning(Languages::TextCanNotStartInErrorState);
return false;
}
if (state == LocoStateTerminated)
{
locoThread.join();
state = LocoStateManual;
}
if (state != LocoStateManual)
{
logger->Info(Languages::TextCanNotStartAlreadyRunning);
return false;
}
state = (type == AutoModeTypeTimetable ? LocoStateTimetableGetFirst : LocoStateAutomodeGetFirst);
locoThread = std::thread(&DataModel::LocoBase::AutoMode, this);
return true;
}
void LocoBase::RequestManualMode()
{
if (state == LocoStateManual || state == LocoStateTerminated)
{
return;
}
requestManualMode = true;
}
bool LocoBase::GoToManualMode()
{
if (state == LocoStateManual)
{
return true;
}
if (state != LocoStateTerminated)
{
return false;
}
locoThread.join();
state = LocoStateManual;
return true;
}
void LocoBase::ForceManualMode()
{
{
std::lock_guard Guard(stateMutex);
switch (state)
{
case LocoStateManual:
return;
case LocoStateTerminated:
break;
default:
state = LocoStateOff;
break;
}
}
locoThread.join();
state = LocoStateManual;
}
void LocoBase::AutoMode()
{
Utils::Utils::SetMinThreadPriority();
const string& name = GetName();
Utils::Utils::SetThreadName(name);
logger->Info(Languages::TextIsNowInAutoMode);
while (true)
{
{ // sleep must be outside of locked block
std::lock_guard Guard(stateMutex);
if (feedbackIdsReached.IsEmpty() == false)
{
FeedbackID feedbackId = feedbackIdsReached.Dequeue();
if (feedbackId == feedbackIdFirst)
{
FeedbackIdFirstReached();
}
else if (feedbackId == feedbackIdStop)
{
FeedbackIdStopReached();
}
continue;
}
switch (state)
{
case LocoStateOff:
// automode is turned off, terminate thread
logger->Info(Languages::TextIsNowInManualMode);
state = LocoStateTerminated;
requestManualMode = false;
return;
case LocoStateAutomodeGetFirst:
if (requestManualMode)
{
state = LocoStateOff;
break;
}
if (wait > 0)
{
--wait;
break;
}
SearchDestinationFirst();
break;
case LocoStateAutomodeGetSecond:
if (requestManualMode)
{
logger->Info(Languages::TextIsRunningWaitingUntilDestination);
state = LocoStateStopping;
break;
}
if (manager->GetNrOfTracksToReserve() <= 1)
{
break;
}
if (wait > 0)
{
break;
}
SearchDestinationSecond();
break;
case LocoStateTimetableGetFirst:
if (requestManualMode)
{
state = LocoStateOff;
break;
}
if (wait > 0)
{
--wait;
break;
}
GetTimetableDestinationFirst();
break;
case LocoStateTimetableGetSecond:
if (requestManualMode)
{
logger->Info(Languages::TextIsRunningWaitingUntilDestination, name);
state = LocoStateStopping;
break;
}
if (manager->GetNrOfTracksToReserve() <= 1)
{
break;
}
if (wait > 0)
{
break;
}
GetTimetableDestinationSecond();
break;
case LocoStateAutomodeRunning:
case LocoStateTimetableRunning:
// loco is already running, waiting until destination reached
if (requestManualMode)
{
logger->Info(Languages::TextIsRunningWaitingUntilDestination);
state = LocoStateStopping;
}
break;
case LocoStateStopping:
logger->Info(Languages::TextHasNotReachedDestination);
break;
case LocoStateTerminated:
logger->Error(Languages::TextIsInTerminatedState);
state = LocoStateError;
break;
case LocoStateManual:
logger->Error(Languages::TextIsInManualState);
state = LocoStateError;
#include "Fallthrough.h"
case LocoStateError:
logger->Error(Languages::TextIsInErrorState);
manager->LocoBaseSpeed(ControlTypeInternal, this, MinSpeed);
if (requestManualMode)
{
state = LocoStateOff;
}
break;
}
}
// FIXME: make configurable
Utils::Utils::SleepForSeconds(1);
}
}
void LocoBase::SearchDestinationFirst()
{
if (routeFirst != nullptr)
{
state = LocoStateError;
logger->Error(Languages::TextHasAlreadyReservedRoute);
return;
}
Route* route = SearchDestination(trackFrom, true);
PrepareDestinationFirst(route, LocoStateAutomodeGetSecond);
}
void LocoBase::GetTimetableDestinationFirst()
{
if (routeFirst != nullptr)
{
state = LocoStateError;
logger->Error(Languages::TextHasAlreadyReservedRoute);
return;
}
Route* const route = GetDestinationFromTimeTable(trackFrom, true);
if (route == nullptr)
{
logger->Debug(Languages::TextNoValidTimetableEntryFound);
return;
}
PrepareDestinationFirst(route, LocoStateTimetableGetSecond);
}
void LocoBase::PrepareDestinationFirst(Route* const route, const LocoState newState)
{
if (route == nullptr)
{
return;
}
Track* newTrack = manager->GetTrack(route->GetToTrack());
if (newTrack == nullptr)
{
return;
}
bool isOrientationSet = newTrack->SetLocoOrientation(static_cast(route->GetToOrientation()));
if (isOrientationSet == false)
{
return;
}
bool turnLoco = (trackFrom->GetLocoOrientation() != route->GetFromOrientation());
Orientation newLocoOrientation = static_cast(orientation != turnLoco);
if (turnLoco)
{
bool canTurnOrientation = trackFrom->SetLocoOrientation(route->GetFromOrientation());
if (canTurnOrientation == false)
{
return;
}
manager->TrackPublishState(trackFrom);
}
manager->LocoBaseOrientation(ControlTypeInternal, this, newLocoOrientation);
logger->Info(Languages::TextHeadingToVia, newTrack->GetName(), route->GetName());
trackFirst = newTrack;
routeFirst = route;
feedbackIdFirst = FeedbackNone;
feedbackIdReduced = routeFirst->GetFeedbackIdReduced();
feedbackIdCreep = routeFirst->GetFeedbackIdCreep();
feedbackIdStop = routeFirst->GetFeedbackIdStop();
feedbackIdOver = routeFirst->GetFeedbackIdOver();
wait = routeFirst->GetWaitAfterRelease();
// start loco
manager->TrackPublishState(newTrack);
Speed newSpeed;
switch (routeFirst->GetSpeed())
{
case Route::SpeedTravel:
newSpeed = travelSpeed;
break;
case Route::SpeedReduced:
newSpeed = reducedSpeed;
break;
case Route::SpeedCreeping:
default:
newSpeed = creepingSpeed;
break;
}
manager->LocoBaseSpeed(ControlTypeInternal, this, newSpeed);
state = newState;
}
void LocoBase::SearchDestinationSecond()
{
Route* route = SearchDestination(trackFirst, false);
PrepareDestinationSecond(route, LocoStateAutomodeRunning);
}
void LocoBase::GetTimetableDestinationSecond()
{
Route* route = GetDestinationFromTimeTable(trackFirst, false);
if (route == nullptr)
{
return;
}
PrepareDestinationSecond(route, LocoStateTimetableRunning);
}
Route* LocoBase::GetDestinationFromTimeTable(const Track* const track, const bool allowLocoTurn)
{
if (timeTableQueue.IsEmpty())
{
return nullptr;
}
RouteID routeId = timeTableQueue.Dequeue();
Route* const route = manager->GetRoute(routeId);
if (route->GetFromTrack() != track->GetID())
{
return nullptr;
}
bool ret = ReserveRoute(track, allowLocoTurn, route);
if (!ret)
{
return nullptr;
}
logger->Debug(Languages::TextUsingRouteFromTimetable, route->GetID());
return route;
}
bool LocoBase::AddTimeTable(const ObjectIdentifier& identifier)
{
switch (identifier.GetObjectType())
{
case ObjectTypeRoute:
timeTableQueue.Enqueue(identifier.GetObjectID());
logger->Debug(Languages::TextAddingRouteToTimetable, identifier.GetObjectID());
return true;
case ObjectTypeTimeTable:
// FIXME: TimeTable function is not yet implemented
return false;
default:
return false;
}
}
void LocoBase::PrepareDestinationSecond(Route* const route, const LocoState newState)
{
if (route == nullptr)
{
return;
}
Track* newTrack = manager->GetTrack(route->GetToTrack());
if (newTrack == nullptr)
{
return;
}
const bool isOrientationSet = newTrack->SetLocoOrientation(static_cast(route->GetToOrientation()));
if (isOrientationSet == false)
{
return;
}
logger->Info(Languages::TextHeadingToViaVia, newTrack->GetName(), routeFirst->GetName(), route->GetName());
trackSecond = newTrack;
routeSecond = route;
feedbackIdFirst = feedbackIdStop;
feedbackIdFirstCreep = feedbackIdCreep;
feedbackIdFirstReduced = feedbackIdReduced;
feedbackIdOver = routeSecond->GetFeedbackIdOver();
feedbackIdStop = routeSecond->GetFeedbackIdStop();
feedbackIdCreep = routeSecond->GetFeedbackIdCreep();
feedbackIdReduced = routeSecond->GetFeedbackIdReduced();
wait = routeSecond->GetWaitAfterRelease();
manager->TrackPublishState(newTrack);
state = newState;
}
Route* LocoBase::SearchDestination(const Track* const track, const bool allowLocoTurn)
{
if (manager->Booster() == BoosterStateStop)
{
return nullptr;
}
logger->Debug(Languages::TextLookingForDestination, track->GetName());
if (routeSecond != nullptr)
{
state = LocoStateError;
logger->Error(Languages::TextHasAlreadyReservedRoute);
return nullptr;
}
if (track == nullptr)
{
state = LocoStateOff;
logger->Info(Languages::TextIsNotOnTrack);
return nullptr;
}
const ObjectIdentifier locoBaseOfTrack = track->GetLocoBase();
if (locoBaseOfTrack != GetObjectIdentifier())
{
state = LocoStateError;
logger->Error(Languages::TextIsOnOcupiedTrack, track->GetName(), manager->GetLocoBaseName(locoBaseOfTrack));
return nullptr;
}
vector validRoutes;
track->GetValidRoutes(logger, this, allowLocoTurn, validRoutes);
for (auto route : validRoutes)
{
bool ret = ReserveRoute(track, allowLocoTurn, route);
if (ret)
{
return route;
}
}
logger->Debug(Languages::TextNoValidRouteFound, GetName());
return nullptr;
}
bool LocoBase::ReserveRoute(const Track* const track, const bool allowLocoTurn, Route* const route)
{
logger->Debug(Languages::TextExecutingRoute, route->GetName());
const ObjectIdentifier locoBaseIdentifier = GetObjectIdentifier();
if (route->Reserve(logger, locoBaseIdentifier) == false)
{
return false;
}
if (route->Lock(logger, locoBaseIdentifier) == false)
{
route->Release(logger, locoBaseIdentifier);
return false;
}
Track* newTrack = manager->GetTrack(route->GetToTrack());
if (newTrack == nullptr)
{
route->Release(logger, locoBaseIdentifier);
return false;
}
bool canSetOrientation = newTrack->CanSetLocoBaseOrientation(route->GetToOrientation(), locoBaseIdentifier);
if (canSetOrientation == false)
{
route->Release(logger, locoBaseIdentifier);
newTrack->Release(logger, locoBaseIdentifier);
return false;
}
if (!allowLocoTurn && track->GetLocoOrientation() != route->GetFromOrientation())
{
route->Release(logger, locoBaseIdentifier);
newTrack->Release(logger, locoBaseIdentifier);
return false;
}
if (route->Execute(logger, locoBaseIdentifier) == false)
{
route->Release(logger, locoBaseIdentifier);
newTrack->Release(logger, locoBaseIdentifier);
return false;
}
return true;
}
Speed LocoBase::GetRouteSpeed(const Route::Speed routeSpeed)
{
switch (routeSpeed)
{
case Route::SpeedTravel:
return travelSpeed;
case Route::SpeedReduced:
return reducedSpeed;
case Route::SpeedCreeping:
return creepingSpeed;
default:
return MinSpeed;
}
}
void LocoBase::LocationReached(const FeedbackID feedbackID)
{
if (feedbackID == feedbackIdOver)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, MinSpeed);
manager->Booster(ControlTypeInternal, BoosterStateStop);
logger->Error(Languages::TextHitOverrun, manager->GetFeedbackName(feedbackID));
return;
}
if (feedbackID == feedbackIdStop)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, MinSpeed);
if (feedbackIdFirst != 0)
{
feedbackIdsReached.Enqueue(feedbackIdFirst);
}
feedbackIdsReached.Enqueue(feedbackIdStop);
return;
}
if (feedbackID == feedbackIdCreep)
{
if (speed > creepingSpeed)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, creepingSpeed);
}
if (feedbackIdFirst != 0)
{
feedbackIdsReached.Enqueue(feedbackIdFirst);
}
return;
}
if (feedbackID == feedbackIdReduced)
{
if (speed > reducedSpeed)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, reducedSpeed);
}
if (feedbackIdFirst != 0)
{
feedbackIdsReached.Enqueue(feedbackIdFirst);
}
return;
}
if (feedbackID == feedbackIdFirst)
{
Speed newSpeed = GetRouteSpeed(routeSecond->GetSpeed());
if (speed > newSpeed)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, newSpeed);
}
feedbackIdsReached.Enqueue(feedbackIdFirst);
return;
}
if (feedbackID == feedbackIdFirstCreep)
{
Route::Speed routeSpeed = routeSecond->GetSpeed();
switch (routeSpeed)
{
case Route::SpeedCreeping:
if (speed > creepingSpeed)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, creepingSpeed);
}
break;
default:
break;
}
return;
}
if (feedbackID == feedbackIdFirstReduced)
{
Route::Speed routeSpeed = routeSecond->GetSpeed();
switch (routeSpeed)
{
case Route::SpeedReduced:
case Route::SpeedCreeping:
if (speed > reducedSpeed)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, reducedSpeed);
}
break;
default:
break;
}
return;
}
}
void LocoBase::SetSpeed(const Speed speed)
{
this->speed = speed;
}
void LocoBase::SetFunctionState(const DataModel::LocoFunctionNr nr,
const DataModel::LocoFunctionState state)
{
functions.SetFunctionState(nr, state);
}
void LocoBase::SetOrientation(const Orientation orientation)
{
this->orientation = orientation;
}
void LocoBase::FeedbackIdFirstReached()
{
if (routeFirst == nullptr || trackFrom == nullptr)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, MinSpeed);
state = LocoStateError;
logger->Error(Languages::TextIsInAutomodeWithoutRouteTrack);
return;
}
Speed newSpeed = GetRouteSpeed(routeSecond->GetSpeed());
if (speed != newSpeed)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, newSpeed);
}
routeFirst->Release(logger, GetObjectIdentifier());
routeFirst = routeSecond;
routeSecond = nullptr;
trackFrom->Release(logger, GetObjectIdentifier());
trackFrom = trackFirst;
trackFirst = trackSecond;
trackSecond = nullptr;
// set state
switch (state)
{
case LocoStateAutomodeRunning:
state = LocoStateAutomodeGetSecond;
break;
case LocoStateTimetableRunning:
state = LocoStateTimetableGetSecond;
break;
case LocoStateStopping:
// do nothing
break;
default:
logger->Error(Languages::TextIsInInvalidAutomodeState, state, manager->GetFeedbackName(feedbackIdFirst));
state = LocoStateError;
break;
}
feedbackIdFirstCreep = FeedbackNone;
feedbackIdFirstReduced = FeedbackNone;
feedbackIdFirst = FeedbackNone;
}
void LocoBase::FeedbackIdStopReached()
{
if (routeFirst == nullptr || trackFrom == nullptr)
{
manager->LocoBaseSpeed(ControlTypeInternal, this, MinSpeed);
state = LocoStateError;
logger->Error(Languages::TextIsInAutomodeWithoutRouteTrack);
return;
}
// FIXME: This is needed if FeedbackIdFirst is not hit
manager->LocoBaseSpeed(ControlTypeInternal, this, MinSpeed);
manager->LocoDestinationReached(this, routeFirst, trackFrom);
routeFirst->Release(logger, GetObjectIdentifier());
routeFirst = nullptr;
trackFrom->Release(logger, GetObjectIdentifier());
trackFrom = trackFirst;
trackFirst = nullptr;
logger->Info(Languages::TextReachedItsDestination);
// set state
switch (state)
{
case LocoStateAutomodeGetSecond:
state = LocoStateAutomodeGetFirst;
break;
case LocoStateTimetableGetSecond:
state = LocoStateTimetableGetFirst;
break;
case LocoStateStopping:
state = LocoStateOff;
break;
default:
logger->Error(Languages::TextIsInInvalidAutomodeState, state, manager->GetFeedbackName(feedbackIdStop));
state = LocoStateError;
break;
}
feedbackIdStop = FeedbackNone;
feedbackIdCreep = FeedbackNone;
feedbackIdReduced = FeedbackNone;
}
DataModel::LocoFunctionNr LocoBase::GetFunctionNumberFromFunctionIcon(DataModel::LocoFunctionIcon icon) const
{
for (DataModel::LocoFunctionNr nr = 0; nr < NumberOfLocoFunctions; ++nr)
{
if (icon == functions.GetFunctionIcon(nr))
{
return nr;
}
}
return NumberOfLocoFunctions;
}
LocoBase& LocoBase::operator=(const Hardware::LocoCacheEntry& loco)
{
SetControlID(loco.GetControlID());
SetAddress(loco.GetAddress());
SetProtocol(loco.GetProtocol());
SetName(loco.GetName());
SetMatchKey(loco.GetMatchKey());
ConfigureFunctions(loco.GetFunctionStates());
return *this;
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LocoBase.h 0000664 0000000 0000000 00000021121 14751611131 0020317 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include
#include
#include "DataTypes.h"
#include "Logger/Logger.h"
#include "DataModel/HardwareHandle.h"
#include "DataModel/LocoFunctions.h"
#include "DataModel/Object.h"
#include "DataModel/Relation.h"
#include "DataModel/Route.h"
#include "Utils/ThreadSafeQueue.h"
class Manager;
namespace Hardware
{
class LocoCacheEntry;
}
namespace DataModel
{
class ObjectIdentifier;
class Route;
class Track;
class LocoBase : public Object, public HardwareHandle
{
public:
enum NrOfTracksToReserve : unsigned char
{
ReserveOne = 1,
ReserveTwo = 2
};
enum AutoModeType : unsigned char
{
AutoModeTypeFull = 0,
AutoModeTypeTimetable
};
LocoBase() = delete;
LocoBase(const LocoBase&) = delete;
LocoBase& operator=(const LocoBase&) = delete;
inline LocoBase(Manager* manager, const LocoID locoID)
: Object(locoID),
HardwareHandle(),
manager(manager),
length(0),
pushpull(false),
maxSpeed(0),
travelSpeed(0),
reducedSpeed(0),
creepingSpeed(0),
propulsion(PropulsionUnknown),
trainType(TrainTypeUnknown),
speed(MinSpeed),
orientation(OrientationRight),
state(LocoStateManual),
requestManualMode(false),
trackFrom(nullptr),
trackFirst(nullptr),
trackSecond(nullptr),
routeFirst(nullptr),
routeSecond(nullptr),
feedbackIdFirstReduced(FeedbackNone),
feedbackIdFirstCreep(FeedbackNone),
feedbackIdFirst(FeedbackNone),
feedbackIdReduced(FeedbackNone),
feedbackIdCreep(FeedbackNone),
feedbackIdStop(FeedbackNone),
feedbackIdOver(FeedbackNone),
feedbackIdsReached(),
wait(0),
matchKey("")
{
logger = Logger::Logger::GetLogger(GetName());
}
inline LocoBase(Manager* manager, const std::string& serialized)
: LocoBase(manager, LocoNone)
{
LocoBase::Deserialize(serialized);
logger = Logger::Logger::GetLogger(GetName());
}
virtual ~LocoBase();
inline Logger::Logger* GetLogger()
{
return logger;
}
std::string Serialize() const override;
bool Deserialize(const std::string& serialized) override;
bool Deserialize(const std::map& arguments) override;
virtual void SetName(const std::string& name) override
{
Object::SetName(name);
logger = Logger::Logger::GetLogger(name);
}
bool GoToAutoMode(const AutoModeType type = AutoModeTypeFull);
void RequestManualMode();
bool GoToManualMode();
bool AddTimeTable(const ObjectIdentifier& identifier);
bool SetTrack(const TrackID trackID);
TrackID GetTrackId();
bool Release();
bool IsRunningFromTrack(const TrackID trackID) const;
void LocationReached(const FeedbackID feedbackID);
virtual void SetSpeed(const Speed speed);
inline Speed GetSpeed() const
{
return speed;
}
virtual void SetFunctionState(const DataModel::LocoFunctionNr nr,
const DataModel::LocoFunctionState state);
inline DataModel::LocoFunctionState GetFunctionState(const DataModel::LocoFunctionNr nr) const
{
return functions.GetFunctionState(nr);
}
inline std::vector GetFunctionStates() const
{
return functions.GetFunctionStates();
}
inline void GetFunctions(LocoFunctionEntry* out) const
{
functions.GetFunctions(out);
}
inline void ConfigureFunctions(const std::vector& newEntries)
{
functions.ConfigureFunctions(newEntries);
}
virtual void SetOrientation(const Orientation orientation);
inline Orientation GetOrientation() const
{
return orientation;
}
inline bool IsInManualMode() const
{
return this->state == LocoStateManual;
}
inline bool IsInUse() const
{
return this->speed > 0
|| this->state != LocoStateManual
|| this->trackFrom != nullptr
|| this->routeFirst != nullptr;
}
inline Length GetLength() const
{
return length;
}
inline void SetLength(const Length length)
{
this->length = length;
}
inline bool GetPushpull() const
{
return pushpull;
}
inline Speed GetMaxSpeed() const
{
return maxSpeed;
}
inline Speed GetTravelSpeed() const
{
return travelSpeed;
}
inline Speed GetReducedSpeed() const
{
return reducedSpeed;
}
inline Speed GetCreepingSpeed() const
{
return creepingSpeed;
}
inline void SetPushpull(const bool pushpull)
{
this->pushpull = pushpull;
}
inline void SetMaxSpeed(const Speed speed)
{
maxSpeed = speed;
}
inline void SetTravelSpeed(const Speed speed)
{
travelSpeed = speed;
}
inline void SetReducedSpeed(const Speed speed)
{
reducedSpeed = speed;
}
inline void SetCreepingSpeed(const Speed speed)
{
creepingSpeed = speed;
}
inline void SetPropulsion(const Propulsion propulsion)
{
this->propulsion = propulsion;
}
virtual Propulsion GetPropulsion() const;
inline void SetTrainType(const TrainType trainType)
{
this->trainType = trainType;
}
inline TrainType GetTrainType() const
{
return trainType;
}
inline void SetMatchKey(const std::string& matchKey)
{
this->matchKey = matchKey;
}
inline void ClearMatchKey()
{
matchKey.clear();
}
inline std::string GetMatchKey() const
{
return matchKey;
}
DataModel::LocoFunctionNr GetFunctionNumberFromFunctionIcon(DataModel::LocoFunctionIcon icon) const;
inline LocoID GetLocoIdWithPrefix() const
{
return GetID() + (GetObjectType() == ObjectTypeMultipleUnit ? MultipleUnitIdPrefix : 0);
}
LocoBase& operator=(const Hardware::LocoCacheEntry& loco);
protected:
Manager* manager;
private:
enum LocoState : unsigned char
{
LocoStateManual = 0,
LocoStateTerminated,
LocoStateOff,
LocoStateAutomodeGetFirst,
LocoStateAutomodeGetSecond,
LocoStateAutomodeRunning,
LocoStateTimetableGetFirst,
LocoStateTimetableGetSecond,
LocoStateTimetableRunning,
LocoStateStopping,
LocoStateError
};
void SetMinThreadPriorityAndThreadName();
void AutoMode();
void SearchDestinationFirst();
void GetTimetableDestinationFirst();
void PrepareDestinationFirst(Route* const route, const LocoState newState);
void SearchDestinationSecond();
void GetTimetableDestinationSecond();
DataModel::Route* GetDestinationFromTimeTable(const Track* const track, const bool allowLocoTurn);
void PrepareDestinationSecond(Route* const route, const LocoState newState);
DataModel::Route* SearchDestination(const DataModel::Track* const oldToTrack, const bool allowLocoTurn);
bool ReserveRoute(const Track* const track, const bool allowLocoTurn, Route* const route);
void FeedbackIdFirstReached();
void FeedbackIdStopReached();
void ForceManualMode();
bool GoToAutoModeInternal(const LocoState newState);
Speed GetRouteSpeed(const Route::Speed routeSpeed);
mutable std::mutex stateMutex;
std::thread locoThread;
Length length;
bool pushpull;
Speed maxSpeed;
Speed travelSpeed;
Speed reducedSpeed;
Speed creepingSpeed;
Propulsion propulsion;
TrainType trainType;
Speed speed;
Orientation orientation;
volatile LocoState state;
volatile bool requestManualMode;
Track* trackFrom;
Track* trackFirst;
Track* trackSecond;
Route* routeFirst;
Route* routeSecond;
volatile FeedbackID feedbackIdFirstReduced;
volatile FeedbackID feedbackIdFirstCreep;
volatile FeedbackID feedbackIdFirst;
volatile FeedbackID feedbackIdReduced;
volatile FeedbackID feedbackIdCreep;
volatile FeedbackID feedbackIdStop;
volatile FeedbackID feedbackIdOver;
Utils::ThreadSafeQueue feedbackIdsReached;
Pause wait;
Utils::ThreadSafeQueue timeTableQueue;
std::string matchKey;
LocoFunctions functions;
Logger::Logger* logger;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LocoConfig.h 0000664 0000000 0000000 00000010225 14751611131 0020655 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include "DataModel/Loco.h"
#include "DataModel/MultipleUnit.h"
#include "Hardware/LocoCache.h"
namespace DataModel
{
class LocoConfig
{
public:
inline LocoConfig(const LocoType type = LocoTypeLoco)
: controlId(ControlNone),
locoId(LocoNone),
address(AddressDefault),
protocol(ProtocolNone),
type(type),
isInUse(false)
{
}
inline LocoConfig(const DataModel::Loco& loco)
: controlId(loco.GetControlID()),
locoId(loco.GetID()),
address(loco.GetAddress()),
protocol(loco.GetProtocol()),
type(LocoTypeLoco),
name(loco.GetName()),
matchKey(loco.GetMatchKey()),
isInUse(loco.IsInUse())
{
ConfigureFunctions(loco.GetFunctionStates());
}
inline LocoConfig(const Hardware::LocoCacheEntry& loco)
: controlId(loco.GetControlID()),
locoId(loco.GetLocoID()),
address(loco.GetAddress()),
protocol(loco.GetProtocol()),
type(loco.GetType()),
name(loco.GetName()),
matchKey(loco.GetMatchKey()),
isInUse(false)
{
ConfigureFunctions(loco.GetFunctionStates());
}
inline LocoConfig& operator=(const DataModel::Loco& loco)
{
controlId = loco.GetControlID();
locoId = loco.GetID();
address = loco.GetAddress();
protocol = loco.GetProtocol();
type = LocoTypeLoco;
name = loco.GetName();
matchKey = loco.GetMatchKey();
isInUse = loco.IsInUse();
ConfigureFunctions(loco.GetFunctionStates());
return *this;
}
inline LocoConfig& operator=(const Hardware::LocoCacheEntry& loco)
{
controlId = loco.GetControlID();
locoId = loco.GetLocoID();
address = loco.GetAddress();
protocol = loco.GetProtocol();
type = loco.GetType();
name = loco.GetName();
matchKey = loco.GetMatchKey();
ConfigureFunctions(loco.GetFunctionStates());
return *this;
}
inline LocoConfig& operator=(const DataModel::MultipleUnit& multipleUnit)
{
controlId = multipleUnit.GetControlID();
locoId = multipleUnit.GetID();
address = multipleUnit.GetAddress();
protocol = ProtocolNone;
type = LocoTypeMultipleUnit;
name = multipleUnit.GetName();
matchKey = multipleUnit.GetMatchKey();
isInUse = multipleUnit.IsInUse();
ConfigureFunctions(multipleUnit.GetFunctionStates());
return *this;
}
inline ControlID GetControlId() const
{
return controlId;
}
inline LocoID GetLocoId() const
{
return locoId;
}
inline Address GetAddress() const
{
return address;
}
inline Protocol GetProtocol() const
{
return protocol;
}
inline LocoType GetType() const
{
return type;
}
inline void SetType(const LocoType type)
{
this->type = type;
}
inline std::string GetName() const
{
return name;
}
inline void SetName(const std::string& name)
{
this->name = name;
}
inline std::string GetMatchKey() const
{
return matchKey;
}
inline bool IsInUse() const
{
return isInUse;
}
inline void GetFunctions(LocoFunctionEntry* out) const
{
functions.GetFunctions(out);
}
inline void ConfigureFunctions(const std::vector& newEntries)
{
functions.ConfigureFunctions(newEntries);
}
private:
ControlID controlId;
LocoID locoId;
Address address;
Protocol protocol;
LocoType type;
std::string name;
std::string matchKey;
bool isInUse;
LocoFunctions functions;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LocoFunctions.cpp 0000664 0000000 0000000 00000301647 14751611131 0021766 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include
#include "DataModel/LocoFunctions.h"
#include "Utils/Utils.h"
namespace DataModel
{
LocoFunctions::LocoFunctions()
{
for (LocoFunctionNr nr = 0; nr < NumberOfLocoFunctions; ++nr)
{
entries[nr].nr = nr;
entries[nr].type = LocoFunctionTypeNone;
entries[nr].icon = LocoFunctionIconNone;
entries[nr].timer = 0;
}
}
std::vector LocoFunctions::GetFunctionStates() const
{
std::vector out;
for (LocoFunctionNr i = 0; i < NumberOfLocoFunctions; ++i)
{
if (entries[i].type == LocoFunctionTypeNone)
{
continue;
}
out.push_back(entries[i]);
}
return out;
}
void LocoFunctions::ConfigureFunctions(const std::vector& newEntries)
{
for (LocoFunctionNr nr = 0; nr < NumberOfLocoFunctions; ++nr)
{
entries[nr].type = LocoFunctionTypeNone;
}
for (const LocoFunctionEntry& newEntry : newEntries)
{
LocoFunctionNr nr = newEntry.nr;
LocoFunctionState state = entries[nr].state;
entries[nr] = newEntry;
entries[nr].state = state;
}
}
void LocoFunctions::SetFunctionStates(const std::vector& newEntries)
{
for (LocoFunctionNr nr = 0; nr < NumberOfLocoFunctions; ++nr)
{
entries[nr].type = LocoFunctionTypeNone;
}
for (const LocoFunctionEntry& newEntry : newEntries)
{
LocoFunctionNr nr = newEntry.nr;
entries[nr] = newEntry;
}
}
std::string LocoFunctions::Serialize() const
{
std::string out;
for (LocoFunctionNr nr = 0; nr < NumberOfLocoFunctions; ++nr)
{
if (entries[nr].type == LocoFunctionTypeNone)
{
continue;
}
out += "f" + std::to_string(static_cast(nr));
out += ":" + std::to_string(static_cast(entries[nr].state));
out += ":" + std::to_string(static_cast(entries[nr].type));
out += ":" + std::to_string(static_cast(entries[nr].icon));
if (entries[nr].type != LocoFunctionTypeTimer)
{
continue;
}
out += ":" + std::to_string(static_cast(entries[nr].icon));
}
return out;
}
bool LocoFunctions::Deserialize(const std::string& serialized)
{
std::deque functionsSerialized;
Utils::Utils::SplitString(serialized, "f", functionsSerialized);
for (std::string& functionSerialized : functionsSerialized)
{
if (functionSerialized.size() == 0)
{
continue;
}
std::deque functionTexts;
Utils::Utils::SplitString(functionSerialized, ":", functionTexts);
const size_t nrOfTexts = functionTexts.size();
if (nrOfTexts != 4 && nrOfTexts != 5)
{
continue;
}
LocoFunctionNr nr = Utils::Utils::StringToInteger(functionTexts.front());
functionTexts.pop_front();
entries[nr].state = static_cast(Utils::Utils::StringToInteger(functionTexts.front(), LocoFunctionStateOff));
functionTexts.pop_front();
entries[nr].type = static_cast(Utils::Utils::StringToInteger(functionTexts.front(), LocoFunctionTypePermanent));
functionTexts.pop_front();
entries[nr].icon = static_cast(Utils::Utils::StringToInteger(functionTexts.front(), LocoFunctionIconDefault));
functionTexts.pop_front();
if (nrOfTexts == 4)
{
entries[nr].timer = 0;
continue;
}
entries[nr].timer = static_cast(Utils::Utils::StringToInteger(functionTexts.front(), 0));
functionTexts.pop_front();
}
return true;
}
std::string LocoFunctions::GetLocoFunctionIcon(const LocoFunctionNr nr, const LocoFunctionIcon icon)
{
switch (icon)
{
case LocoFunctionIconNone:
return " ";
case LocoFunctionIconShuntingMode:
return ""
""
" "
" "
" "
" ";
case LocoFunctionIconInertia:
return ""
""
""
"kg "
" ";
case LocoFunctionIconLight:
return ""
""
""
""
""
""
""
""
""
""
""
""
" ";
case LocoFunctionIconHeadlightLowBeamForward:
return ""
""
""
""
""
""
" ";
case LocoFunctionIconHeadlightLowBeamReverse:
return ""
""
""
""
""
""
" ";
case LocoFunctionIconHeadlightHighBeamForward:
return ""
""
""
""
""
""
""
" ";
case LocoFunctionIconHeadlightHighBeamReverse:
return ""
""
""
""
""
""
""
" ";
case LocoFunctionIconBacklightForward:
return ""
""
""
""
""
""
""
""
" ";
case LocoFunctionIconBacklightReverse:
return ""
""
""
""
""
""
""
""
" ";
case LocoFunctionIconShuntingLight:
return ""
""
""
" "
" "
" "
" "
" ";
case LocoFunctionIconBlinkingLight:
return ""
""
""
" "
" "
" "
" "
" "
" "
" "
" ";
case LocoFunctionIconInteriorLight1:
return ""
""
""
""
""
""
""
""
"1 "
" ";
case LocoFunctionIconInteriorLight2:
return ""
""
""
""
""
""
""
""
"2 "
" ";
case LocoFunctionIconTableLight1:
return ""
""
""
""
""
""
""
""
""
""
""
""
" ";
case LocoFunctionIconTableLight2:
return ""
""
""
""
""
""
""
""
""
""
""
""
" ";
case LocoFunctionIconTableLight3:
return ""
""
""
""
""
""
""
""
""
""
""
""
" ";
case LocoFunctionIconCabLight1:
return ""
""
""
" "
""
""
""
""
" ";
case LocoFunctionIconCabLight2:
return ""
""
""
" "
""
""
""
""
" ";
case LocoFunctionIconCabLight12:
return ""
""
""
" "
" "
""
""
""
""
" ";
case LocoFunctionIconDriversDeskLight:
return ""
""
""
""
""
" ";
case LocoFunctionIconTrainDestinationIndicator:
return ""
""
"Zürich "
""
""
""
""
""
""
" ";
case LocoFunctionIconLocomotiveNumberIndicator:
return ""
""
"X4014 "
""
""
""
""
""
""
" ";
case LocoFunctionIconEngineLight:
return ""
""
""
""
""
""
""
""
""
""
""
""
""
""
" "
""
""
""
""
""
""
" "
" ";
case LocoFunctionIconFireBox:
return ""
""
" "
" "
" "
" "
" "
" "
" ";
case LocoFunctionIconStairsLight:
return ""
""
""
""
""
""
""
""
""
" ";
case LocoFunctionIconSmokeGenerator:
return ""
""
" "
" "
" ";
case LocoFunctionIconTelex1:
return ""
""
""
""
" ";
case LocoFunctionIconTelex2:
return ""
""
""
""
" ";
case LocoFunctionIconTelex12:
return ""
""
""
" ";
case LocoFunctionIconPanto1:
return ""
""
""
""
""
""
" ";
case LocoFunctionIconPanto2:
return ""
""
""
""
""
""
" ";
case LocoFunctionIconPanto12:
return ""
""
""
""
""
" ";
case LocoFunctionIconUp:
return ""
""
" ";
case LocoFunctionIconDown:
return ""
""
" ";
case LocoFunctionIconUpDown1:
return ""
""
" ";
case LocoFunctionIconUpDown2:
return ""
""
" ";
case LocoFunctionIconLeft:
return ""
""
" ";
case LocoFunctionIconRight:
return ""
""
" ";
case LocoFunctionIconLeftRight:
return ""
""
" ";
case LocoFunctionIconTurnLeft:
return ""
""
" ";
case LocoFunctionIconTurnRight:
return ""
""
" ";
case LocoFunctionIconTurn:
return ""
""
" ";
case LocoFunctionIconCrane:
return ""
""
""
""
" ";
case LocoFunctionIconMagnet:
return ""
""
""
""
""
" ";
case LocoFunctionIconCraneHook:
return ""
""
" ";
case LocoFunctionIconFan:
return ""
" "
""
""
""
""
" "
" "
" "
" "
" ";
case LocoFunctionIconBreak:
return ""
" "
" "
" "
""
""
" ";
case LocoFunctionIconNoSound:
return ""
""
""
" "
" "
" "
""
""
" ";
case LocoFunctionIconSoundGeneral:
return ""
""
""
" "
" "
" "
" ";
case LocoFunctionIconRunning1:
return ""
""
""
""
""
""
" "
" "
"1 "
" "
" "
" "
" "
" ";
case LocoFunctionIconRunning2:
return ""
""
""
""
""
""
" "
" "
"2 "
" "
" "
" "
" "
" ";
case LocoFunctionIconEngine1:
return ""
" "
""
"M "
" "
" "
" "
" "
"1 "
" ";
case LocoFunctionIconEngine2:
return ""
" "
""
"M "
" "
" "
" "
" "
"2 "
" ";
case LocoFunctionIconBreak1:
return ""
" "
" "
" "
""
""
" "
" "
" "
"1 "
" ";
case LocoFunctionIconBreak2:
return ""
" "
" "
" "
""
""
" "
" "
" "
"2 "
" ";
case LocoFunctionIconCurve:
return ""
""
""
""
""
""
""
""
" "
" "
" "
" "
" ";
case LocoFunctionIconHorn1:
return ""
""
" "
" "
" "
"1 "
" ";
case LocoFunctionIconHorn2:
return ""
""
" "
" "
" "
"2 "
" ";
case LocoFunctionIconWhistle1:
return ""
" "
""
" "
" "
" "
" ";
case LocoFunctionIconWhistle2:
return ""
""
" "
" "
" "
" ";
case LocoFunctionIconBell:
return ""
""
""
" "
" "
" "
" "
" ";
case LocoFunctionIconStationAnnouncement1:
return ""
""
" "
" "
" "
"1 "
" ";
case LocoFunctionIconStationAnnouncement2:
return ""
""
" "
" "
" "
"2 "
" ";
case LocoFunctionIconStationAnnouncement3:
return ""
""
" "
" "
" "
"3 "
" ";
case LocoFunctionIconSpeak:
return ""
""
" ";
case LocoFunctionIconRadio:
return ""
""
" "
" "
" "
" "
" ";
case LocoFunctionIconMusic1:
return ""
""
""
""
" "
" "
" "
" "
"1 "
" ";
case LocoFunctionIconMusic2:
return ""
""
""
""
" "
" "
" "
" "
"2 "
" ";
case LocoFunctionIconOpenDoor:
return ""
""
""
" ";
case LocoFunctionIconCloseDoor:
return ""
""
""
" ";
case LocoFunctionIconFan1:
return ""
" "
""
""
""
""
"1 "
" "
" "
" "
" "
" ";
case LocoFunctionIconFan2:
return ""
" "
""
""
""
""
"2 "
" "
" "
" "
" "
" ";
case LocoFunctionIconFan3:
return ""
" "
""
""
""
""
"3 "
" "
" "
" "
" "
" ";
case LocoFunctionIconShovelCoal:
return ""
""
""
" "
" "
" "
" ";
case LocoFunctionIconCompressedAir:
return ""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconReliefValve:
return ""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconSteamBlowOut:
return ""
""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconSteamBlow:
return ""
""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconDrainValve:
return ""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconShakingRust:
return ""
""
""
""
""
""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconAirPump:
return ""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconWaterPump:
return ""
""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconBufferPush:
return ""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconGenerator:
return ""
" "
" "
" "
" "
" "
" "
" "
" "
" "
" ";
case LocoFunctionIconGearBox:
return ""
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" ";
case LocoFunctionIconGearUp:
return ""
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
""
""
" ";
case LocoFunctionIconGearDown:
return ""
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
" "
""
" ";
case LocoFunctionIconFillWater:
return ""
""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconFillDiesel:
return ""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconFillGas:
return ""
""
""
" "
" "
" "
" "
""
" "
" "
" "
" ";
case LocoFunctionIconSand:
return ""
" "
" "
" "
""
" "
" "
" "
" ";
case LocoFunctionIconRailJoint:
return ""
""
""
""
""
""
""
""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconCoupler:
return ""
""
""
" "
" "
" "
" ";
case LocoFunctionIconPanto:
return ""
""
""
""
" "
" "
" "
" ";
case LocoFunctionIconMainSwitch:
return ""
""
""
" "
" "
" "
" ";
case LocoFunctionIconSoundLouder:
return ""
""
""
""
""
" ";
case LocoFunctionIconSoundLower:
return ""
""
""
""
" ";
case LocoFunctionIconNoBreak:
return ""
" "
" "
" "
""
""
" "
" "
" "
""
""
" ";
default:
return ""
"F" + std::to_string(nr) + " "
" ";
}
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/LocoFunctions.h 0000664 0000000 0000000 00000016514 14751611131 0021427 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include "DataModel/Serializable.h"
namespace DataModel
{
typedef uint16_t LocoFunctionNr;
// 16 bit because icon is added with 256 to select f number and icon in same select dropdown box in relation.
static const LocoFunctionNr NumberOfLocoFunctions = 33; // f0 - f32 = 33
enum LocoFunctionState : uint8_t
{
LocoFunctionStateOff = 0,
LocoFunctionStateOn = 1,
LocoFunctionState0s5 = 5,
LocoFunctionState1s0 = 10,
LocoFunctionState1s5 = 15,
LocoFunctionState2s0 = 20,
};
enum LocoFunctionType : uint8_t
{
LocoFunctionTypeNone = 0,
LocoFunctionTypePermanent = 1,
LocoFunctionTypeMoment = 2,
LocoFunctionTypeFlashing = 3, // actually not implemented
LocoFunctionTypeTimer = 4 // actually not implemented
};
enum LocoFunctionIcon : uint16_t
// 16 bit because icon is added with 256 to select f number and icon in same select dropdown box in relation.
{
// Do not change numbers!
// Only add numbers!
// If you add numbers, add them also in
// - ProtocolMaerklin.cpp
// - WebServer::WebClient::HtmlTagRelationObject
// - WebServer::WebClient::HandleLocoEdit
LocoFunctionIconNone = 0,
LocoFunctionIconDefault = 1,
// logical functions
LocoFunctionIconShuntingMode = 2,
LocoFunctionIconInertia,
// light functions
LocoFunctionIconLight = 32,
LocoFunctionIconHeadlightLowBeamForward,
LocoFunctionIconHeadlightLowBeamReverse,
LocoFunctionIconHeadlightHighBeamForward,
LocoFunctionIconHeadlightHighBeamReverse,
LocoFunctionIconBacklightForward,
LocoFunctionIconBacklightReverse,
LocoFunctionIconShuntingLight,
LocoFunctionIconBlinkingLight,
LocoFunctionIconInteriorLight1,
LocoFunctionIconInteriorLight2,
LocoFunctionIconTableLight1,
LocoFunctionIconTableLight2,
LocoFunctionIconTableLight3,
LocoFunctionIconCabLight1,
LocoFunctionIconCabLight2,
LocoFunctionIconCabLight12,
LocoFunctionIconDriversDeskLight,
LocoFunctionIconTrainDestinationIndicator,
LocoFunctionIconLocomotiveNumberIndicator,
LocoFunctionIconEngineLight,
LocoFunctionIconFireBox,
LocoFunctionIconStairsLight,
// mechanical functions
LocoFunctionIconSmokeGenerator = 64,
LocoFunctionIconTelex1,
LocoFunctionIconTelex2,
LocoFunctionIconTelex12,
LocoFunctionIconPanto1,
LocoFunctionIconPanto2,
LocoFunctionIconPanto12,
LocoFunctionIconUp,
LocoFunctionIconDown,
LocoFunctionIconUpDown1,
LocoFunctionIconUpDown2,
LocoFunctionIconLeft,
LocoFunctionIconRight,
LocoFunctionIconLeftRight,
LocoFunctionIconTurnLeft,
LocoFunctionIconTurnRight,
LocoFunctionIconTurn,
LocoFunctionIconCrane,
LocoFunctionIconMagnet,
LocoFunctionIconCraneHook,
LocoFunctionIconFan,
LocoFunctionIconBreak,
// sound functions
LocoFunctionIconNoSound = 96,
LocoFunctionIconSoundGeneral,
LocoFunctionIconRunning1,
LocoFunctionIconRunning2,
LocoFunctionIconEngine1,
LocoFunctionIconEngine2,
LocoFunctionIconBreak1,
LocoFunctionIconBreak2,
LocoFunctionIconCurve,
LocoFunctionIconHorn1,
LocoFunctionIconHorn2,
LocoFunctionIconWhistle1,
LocoFunctionIconWhistle2,
LocoFunctionIconBell,
LocoFunctionIconStationAnnouncement1,
LocoFunctionIconStationAnnouncement2,
LocoFunctionIconStationAnnouncement3,
LocoFunctionIconSpeak,
LocoFunctionIconRadio,
LocoFunctionIconMusic1,
LocoFunctionIconMusic2,
LocoFunctionIconOpenDoor,
LocoFunctionIconCloseDoor,
LocoFunctionIconFan1,
LocoFunctionIconFan2,
LocoFunctionIconFan3,
LocoFunctionIconShovelCoal,
LocoFunctionIconCompressedAir,
LocoFunctionIconReliefValve,
LocoFunctionIconSteamBlowOut,
LocoFunctionIconSteamBlow,
LocoFunctionIconDrainValve,
LocoFunctionIconShakingRust,
LocoFunctionIconAirPump,
LocoFunctionIconWaterPump,
LocoFunctionIconBufferPush,
LocoFunctionIconGenerator,
LocoFunctionIconGearBox,
LocoFunctionIconGearUp,
LocoFunctionIconGearDown,
LocoFunctionIconFillWater,
LocoFunctionIconFillDiesel,
LocoFunctionIconFillGas,
LocoFunctionIconSand,
LocoFunctionIconRailJoint,
LocoFunctionIconCoupler,
LocoFunctionIconPanto,
LocoFunctionIconMainSwitch,
LocoFunctionIconSoundLouder,
LocoFunctionIconSoundLower,
LocoFunctionIconNoBreak,
MaxLocoFunctionIcons
};
typedef uint8_t LocoFunctionTimer;
class LocoFunctionEntry
{
public:
inline LocoFunctionEntry()
: nr(0),
state(LocoFunctionStateOff),
type(LocoFunctionTypeNone),
icon(LocoFunctionIconNone),
timer(0)
{
}
LocoFunctionNr nr;
LocoFunctionState state;
LocoFunctionType type;
LocoFunctionIcon icon;
LocoFunctionTimer timer;
};
class LocoFunctions : private Serializable
{
public:
LocoFunctions();
inline LocoFunctions(const std::string& serialized)
: LocoFunctions()
{
Deserialize(serialized);
}
inline void SetFunctionState(const LocoFunctionNr nr, const LocoFunctionState state)
{
if (nr >= NumberOfLocoFunctions)
{
return;
}
entries[nr].state = state;
}
inline void SetFunction(const DataModel::LocoFunctionNr nr,
const DataModel::LocoFunctionType type,
const DataModel::LocoFunctionIcon icon,
const DataModel::LocoFunctionTimer timer)
{
if (nr >= NumberOfLocoFunctions)
{
return;
}
LocoFunctionEntry& entry = entries[nr];
entry.type = type;
entry.icon = icon;
entry.timer = timer;
}
inline void ClearFunction(const DataModel::LocoFunctionNr nr)
{
if (nr >= NumberOfLocoFunctions)
{
return;
}
LocoFunctionEntry& entry = entries[nr];
entry.state = LocoFunctionStateOff;
entry.type = LocoFunctionTypeNone;
entry.icon = LocoFunctionIconNone;
entry.timer = 0;
}
void ConfigureFunctions(const std::vector& newEntries);
void SetFunctionStates(const std::vector& newEntries);
inline LocoFunctionState GetFunctionState(const LocoFunctionNr nr) const
{
if (nr >= NumberOfLocoFunctions)
{
return LocoFunctionStateOff;
}
return entries[nr].state;
}
std::vector GetFunctionStates() const;
inline void GetFunctions(LocoFunctionEntry* out) const
{
for (int nr = 0; nr < NumberOfLocoFunctions; ++nr)
{
out[nr] = entries[nr];
}
}
std::string Serialize() const override;
bool Deserialize(const std::string& serialized) override;
inline LocoFunctionIcon GetFunctionIcon(const LocoFunctionNr nr) const
{
if (nr >= NumberOfLocoFunctions)
{
return LocoFunctionIconNone;
}
return entries[nr].icon;
}
static std::string GetLocoFunctionIcon(const LocoFunctionNr nr, const LocoFunctionIcon icon);
private:
LocoFunctionEntry entries[NumberOfLocoFunctions];
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/MultipleUnit.cpp 0000664 0000000 0000000 00000005352 14751611131 0021626 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include "Manager.h"
#include "MultipleUnit.h"
#include
#include
using std::map;
using std::string;
namespace DataModel
{
std::string MultipleUnit::Serialize() const
{
string str = "objectType=MultipleUnit;";
str += LocoBase::Serialize();
return str;
}
bool MultipleUnit::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
if (!arguments.count("objectType") || arguments.at("objectType").compare("MultipleUnit") != 0)
{
return false;
}
LocoBase::Deserialize(arguments);
return true;
}
Propulsion MultipleUnit::GetPropulsion() const
{
uint8_t slavePropulsion = PropulsionUnknown;
for (auto slave : slaves)
{
Loco* loco = manager->GetLoco(slave->ObjectID2());
if (loco == nullptr)
{
continue;
}
const uint8_t locoPropulsion = loco->GetPropulsion();
slavePropulsion |= locoPropulsion;
}
return static_cast(slavePropulsion);
}
void MultipleUnit::DeleteSlaves()
{
while (slaves.size() > 0)
{
Relation* slave = slaves.back();
slaves.pop_back();
delete slave;
}
}
bool MultipleUnit::AssignSlaves(const std::vector& newslaves)
{
DeleteSlaves();
slaves = newslaves;
return true;
}
void MultipleUnit::SetSpeed(const Speed speed)
{
LocoBase::SetSpeed(speed);
for (auto slave : slaves)
{
manager->LocoBaseSpeed(ControlTypeInternal, slave->ObjectIdentifier2(), speed);
}
}
void MultipleUnit::SetFunctionState(const DataModel::LocoFunctionNr nr,
const DataModel::LocoFunctionState state)
{
LocoBase::SetFunctionState(nr, state);
for (auto slave : slaves)
{
manager->LocoBaseFunctionState(ControlTypeInternal, slave->ObjectIdentifier2(), nr, state);
}
}
void MultipleUnit::SetOrientation(const Orientation orientation)
{
LocoBase::SetOrientation(orientation);
for (auto slave : slaves)
{
manager->LocoBaseOrientation(ControlTypeInternal, slave->ObjectIdentifier2(), OrientationChange);
}
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/MultipleUnit.h 0000664 0000000 0000000 00000004173 14751611131 0021273 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include "DataTypes.h"
#include "DataModel/LocoBase.h"
#include "DataModel/Relation.h"
namespace DataModel
{
class ObjectIdentifier;
class MultipleUnit : public LocoBase
{
public:
MultipleUnit() = delete;
MultipleUnit(const MultipleUnit&) = delete;
MultipleUnit& operator=(const MultipleUnit&) = delete;
inline MultipleUnit(Manager* manager, const MultipleUnitID multipleUnitID)
: LocoBase(manager, multipleUnitID)
{
}
inline MultipleUnit(Manager* manager, const std::string& serialized)
: LocoBase(manager, serialized)
{
MultipleUnit::Deserialize(serialized);
}
virtual ~MultipleUnit()
{
}
inline ObjectType GetObjectType() const override
{
return ObjectTypeMultipleUnit;
}
std::string Serialize() const override;
bool Deserialize(const std::string& serialized) override;
virtual Propulsion GetPropulsion() const override;
void DeleteSlaves();
bool AssignSlaves(const std::vector& newslaves);
inline const std::vector& GetSlaves() const
{
return slaves;
}
void SetSpeed(const Speed speed) override;
void SetFunctionState(const DataModel::LocoFunctionNr nr,
const DataModel::LocoFunctionState state) override;
void SetOrientation(const Orientation orientation) override;
private:
std::vector slaves;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Object.cpp 0000664 0000000 0000000 00000002742 14751611131 0020401 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include "DataModel/Object.h"
#include "Utils/Utils.h"
using std::map;
using std::stringstream;
using std::string;
namespace DataModel
{
std::string Object::Serialize() const
{
return "objectID=" + std::to_string(objectID) + ";name=" + Utils::Utils::UrlEncode(name);
}
bool Object::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
return Object::Deserialize(arguments);
}
bool Object::Deserialize(const map& arguments)
{
objectID = Utils::Utils::GetIntegerMapEntry(arguments, "objectID", ObjectNone);
name = Utils::Utils::UrlDecode(Utils::Utils::GetStringMapEntry(arguments, "name"));
return true;
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Object.h 0000664 0000000 0000000 00000003672 14751611131 0020051 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataTypes.h"
#include "DataModel/ObjectIdentifier.h"
#include "DataModel/Serializable.h"
namespace DataModel
{
class Object : protected Serializable
{
public:
Object(const Object&) = delete;
Object& operator=(const Object&) = delete;
inline Object()
: objectID(ObjectNone),
name(std::to_string(objectID))
{
}
inline Object(const ObjectID objectID)
: objectID(objectID),
name(std::to_string(objectID))
{
}
virtual ~Object()
{
}
virtual ObjectType GetObjectType() const = 0;
virtual std::string Serialize() const override;
virtual bool Deserialize(const std::string& serialized) override;
inline ObjectID GetID() const
{
return objectID;
}
inline ObjectIdentifier GetObjectIdentifier() const
{
return ObjectIdentifier(GetObjectType(), GetID());
}
virtual inline void SetName(const std::string& name)
{
this->name = name;
}
inline const std::string& GetName() const
{
return name;
}
protected:
virtual bool Deserialize(const std::map& arguments);
private:
ObjectID objectID;
std::string name;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/ObjectIdentifier.cpp 0000664 0000000 0000000 00000013714 14751611131 0022405 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include "DataModel/ObjectIdentifier.h"
#include "Utils/Utils.h"
namespace DataModel
{
bool ObjectIdentifier::Deserialize(const std::map& arguments)
{
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "track", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeTrack;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "signal", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeSignal;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "switch", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeSwitch;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "accessory", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeAccessory;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "feedback", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeFeedback;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "route", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeRoute;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "text", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeText;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "pause", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypePause;
return true;
}
objectID = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "multipleunit", ObjectNone));
if (objectID != ObjectNone)
{
objectType = ObjectTypeMultipleUnit;
return true;
}
objectType = ObjectTypeNone;
return false;
}
ObjectIdentifier& ObjectIdentifier::operator=(const std::string& text)
{
if (text.substr(0, 5).compare("track") == 0)
{
objectType = ObjectTypeTrack;
objectID = Utils::Utils::StringToInteger(text.substr(5), ObjectNone);
return *this;
}
if (text.substr(0, 6).compare("signal") == 0)
{
objectType = ObjectTypeSignal;
objectID = Utils::Utils::StringToInteger(text.substr(6), ObjectNone);
return *this;
}
if (text.substr(0, 5).compare("route") == 0)
{
objectType = ObjectTypeRoute;
objectID = Utils::Utils::StringToInteger(text.substr(5), ObjectNone);
return *this;
}
if (text.substr(0, 4).compare("loco") == 0)
{
objectType = ObjectTypeLoco;
objectID = Utils::Utils::StringToInteger(text.substr(4), ObjectNone);
return *this;
}
if (text.substr(0, 8).compare("feedback") == 0)
{
objectType = ObjectTypeFeedback;
objectID = Utils::Utils::StringToInteger(text.substr(8), ObjectNone);
return *this;
}
if (text.substr(0, 9).compare("accessory") == 0)
{
objectType = ObjectTypeAccessory;
objectID = Utils::Utils::StringToInteger(text.substr(9), ObjectNone);
return *this;
}
if (text.substr(0, 6).compare("switch") == 0)
{
objectType = ObjectTypeSwitch;
objectID = Utils::Utils::StringToInteger(text.substr(6), ObjectNone);
return *this;
}
if (text.substr(0, 5).compare("layer") == 0)
{
objectType = ObjectTypeLayer;
objectID = Utils::Utils::StringToInteger(text.substr(5), ObjectNone);
return *this;
}
if (text.substr(0, 7).compare("cluster") == 0)
{
objectType = ObjectTypeCluster;
objectID = Utils::Utils::StringToInteger(text.substr(7), ObjectNone);
return *this;
}
if (text.substr(0, 9).compare("timetable") == 0)
{
objectType = ObjectTypeTimeTable;
objectID = Utils::Utils::StringToInteger(text.substr(9), ObjectNone);
return *this;
}
if (text.substr(0, 4).compare("text") == 0)
{
objectType = ObjectTypeText;
objectID = Utils::Utils::StringToInteger(text.substr(4), ObjectNone);
return *this;
}
if (text.substr(0, 5).compare("pause") == 0)
{
objectType = ObjectTypePause;
objectID = Utils::Utils::StringToInteger(text.substr(5), ObjectNone);
return *this;
}
if (text.substr(0, 12).compare("multipleunit") == 0)
{
objectType = ObjectTypeMultipleUnit;
objectID = Utils::Utils::StringToInteger(text.substr(7), ObjectNone);
return *this;
}
objectType = ObjectTypeTrack;
objectID = Utils::Utils::StringToInteger(text, ObjectNone);
return *this;
}
std::string ObjectIdentifier::ObjectTypeToString(const ObjectType objectType)
{
switch (objectType)
{
case ObjectTypeNone:
return "none";
case ObjectTypeLoco:
return "loco";
case ObjectTypeTrack:
return "track";
case ObjectTypeFeedback:
return "feedback";
case ObjectTypeAccessory:
return "accessory";
case ObjectTypeSwitch:
return "switch";
case ObjectTypeRoute:
return "route";
case ObjectTypeLayer:
return "layer";
case ObjectTypeSignal:
return "signal";
case ObjectTypeCluster:
return "cluster";
case ObjectTypeTimeTable:
return "timetable";
case ObjectTypeText:
return "text";
case ObjectTypePause:
return "pause";
case ObjectTypeMultipleUnit:
return "multipleunit";
}
return "object";
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/ObjectIdentifier.h 0000664 0000000 0000000 00000005666 14751611131 0022061 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataTypes.h"
namespace DataModel
{
class ObjectIdentifier
{
public:
inline ObjectIdentifier()
: objectType(ObjectTypeNone),
objectID(ObjectNone)
{
}
inline ObjectIdentifier(const std::string& text)
{
*this = text;
}
inline ObjectIdentifier(const ObjectType objectType, const ObjectID objectID)
: objectType(objectType),
objectID(objectID)
{
}
inline ObjectIdentifier(const std::map& arguments)
{
Deserialize(arguments);
}
inline ObjectIdentifier(const ObjectIdentifier& other) = default;
inline std::string Serialize() const
{
return GetObjectTypeAsString() + "=" + GetObjectIdAsString();
}
bool Deserialize(const std::map& arguments);
inline ObjectIdentifier& operator=(const ObjectIdentifier& other) = default;
inline void SetObjectType(const ObjectType objectType)
{
this->objectType = objectType;
}
inline void SetObjectID(const ObjectID objectID)
{
this->objectID = objectID;
}
ObjectIdentifier& operator=(const std::string& text);
inline bool operator==(const ObjectIdentifier& other) const
{
return this->objectType == other.objectType && this->objectID == other.objectID;
}
inline bool operator!=(const ObjectIdentifier& other) const
{
return !(*this == other);
}
inline operator std::string() const
{
return GetObjectTypeAsString() + GetObjectIdAsString();
}
inline void Clear()
{
objectType = ObjectTypeNone;
objectID = ObjectNone;
}
inline bool IsSet() const
{
return (objectType != ObjectTypeNone) && (objectID != ObjectNone);
}
inline ObjectType GetObjectType() const
{
return objectType;
}
inline ObjectID GetObjectID() const
{
return objectID;
}
inline std::string GetObjectTypeAsString() const
{
return ObjectTypeToString(objectType);
}
inline std::string GetObjectIdAsString() const
{
return std::to_string(objectID);
}
static std::string ObjectTypeToString(const ObjectType objectType);
private:
ObjectType objectType;
ObjectID objectID;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Relation.cpp 0000664 0000000 0000000 00000015401 14751611131 0020744 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include
#include "DataModel/Relation.h"
#include "Manager.h"
#include "Utils/Utils.h"
using std::map;
using std::stringstream;
using std::string;
namespace DataModel
{
std::string Relation::Serialize() const
{
stringstream ss;
ss << LockableItem::Serialize()
<< ";type=" << static_cast(type)
<< ";objectType1=" << static_cast(ObjectType1())
<< ";objectID1=" << object1.GetObjectID()
<< ";objectType2=" << static_cast(ObjectType2())
<< ";objectID2=" << object2.GetObjectID()
<< ";priority=" << static_cast(priority)
<< ";data=" << static_cast(data);
return ss.str();
}
bool Relation::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
LockableItem::Deserialize(arguments);
object1.SetObjectType(static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "objectType1")));
type = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "type"));
object1.SetObjectID(static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "objectID1")));
object2.SetObjectType(static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "objectType2")));
object2.SetObjectID(static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "objectID2")));
priority = Utils::Utils::GetIntegerMapEntry(arguments, "priority");
data = Utils::Utils::GetIntegerMapEntry(arguments, "data");
return true;
}
bool Relation::Execute(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier, const Delay delay)
{
switch (ObjectType2())
{
case ObjectTypeAccessory:
{
bool ret = manager->AccessoryState(ControlTypeInternal, ObjectID2(), static_cast(data), true);
if (ret == false)
{
return false;
}
break;
}
case ObjectTypeSwitch:
{
bool ret = manager->SwitchState(ControlTypeInternal, ObjectID2(), static_cast(data), true);
if (ret == false)
{
return false;
}
break;
}
case ObjectTypeSignal:
{
bool ret = manager->SignalState(ControlTypeInternal, ObjectID2(), static_cast(data), true);
if (ret == false)
{
return false;
}
break;
}
case ObjectTypeTrack:
manager->TrackSetLocoOrientation(ObjectID2(), static_cast(data));
return true;
case ObjectTypeRoute:
return manager->RouteExecute(logger, locoBaseIdentifier, ObjectID2());
case ObjectTypeLoco:
{
const DataModel::LocoFunctionNr nr = static_cast(ObjectID2());
if (data > DataModel::LocoFunctionStateOn)
{
manager->LocoBaseFunctionState(ControlTypeInternal, locoBaseIdentifier, nr, DataModel::LocoFunctionStateOn);
Utils::Utils::SleepForMilliseconds(static_cast(data) * 100);
manager->LocoBaseFunctionState(ControlTypeInternal, locoBaseIdentifier, nr, DataModel::LocoFunctionStateOff);
}
else
{
manager->LocoBaseFunctionState(ControlTypeInternal, locoBaseIdentifier, nr, static_cast(data));
}
return true;
}
case ObjectTypePause:
Utils::Utils::SleepForMilliseconds(static_cast(data) * 100);
return true;
case ObjectTypeMultipleUnit: // abused for loco orientation
manager->LocoBaseOrientation(ControlTypeInternal, locoBaseIdentifier, static_cast(data));
return true;
default:
return false;
}
Utils::Utils::SleepForMilliseconds(delay);
return true;
}
LockableItem* Relation::GetObject2()
{
switch (ObjectType2())
{
case ObjectTypeAccessory:
return manager->GetAccessory(ObjectID2());
case ObjectTypeSwitch:
return manager->GetSwitch(ObjectID2());
case ObjectTypeTrack:
return manager->GetTrack(ObjectID2());
case ObjectTypeSignal:
return manager->GetSignal(ObjectID2());
case ObjectTypeRoute:
return manager->GetRoute(ObjectID2());
default:
return nullptr;
}
}
bool Relation::Reserve(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier)
{
bool ret = LockableItem::Reserve(logger, locoBaseIdentifier);
if (ret == false)
{
logger->Debug(Languages::TextUnableToReserve);
return false;
}
const ObjectType objectType2 = ObjectType2();
if (objectType2 == ObjectTypeLoco || objectType2 == ObjectTypePause || objectType2 == ObjectTypeMultipleUnit)
{
return true;
}
LockableItem* lockable = GetObject2();
if (lockable == nullptr)
{
logger->Debug(Languages::TextRelationTargetNotFound);
LockableItem::Release(logger, locoBaseIdentifier);
return false;
}
Route* route = dynamic_cast(lockable);
if (route != nullptr)
{
return route->Reserve(logger, locoBaseIdentifier);
}
return lockable->Reserve(logger, locoBaseIdentifier);
}
bool Relation::Lock(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier)
{
bool ret = LockableItem::Lock(logger, locoBaseIdentifier);
if (ret == false)
{
return false;
}
const ObjectType objectType2 = ObjectType2();
if (objectType2 == ObjectTypeLoco || objectType2 == ObjectTypePause || objectType2 == ObjectTypeMultipleUnit)
{
return true;
}
LockableItem* lockable = GetObject2();
if (lockable == nullptr)
{
LockableItem::Release(logger, locoBaseIdentifier);
return false;
}
Route* route = dynamic_cast(lockable);
if (route != nullptr)
{
return route->Lock(logger, locoBaseIdentifier);
}
bool retLockable = lockable->Lock(logger, locoBaseIdentifier);
if (retLockable == true)
{
return true;
}
Object* object = dynamic_cast(lockable);
if (object == nullptr)
{
return false;
}
logger->Debug(Languages::TextUnableToLock, object->GetName());
return false;
}
bool Relation::Release(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier)
{
LockableItem* object = GetObject2();
if (object != nullptr)
{
object->Release(logger, locoBaseIdentifier);
}
return LockableItem::Release(logger, locoBaseIdentifier);
}
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Relation.h 0000664 0000000 0000000 00000007214 14751611131 0020414 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#pragma once
#include
#include
#include "DataModel/Accessory.h"
#include "DataModel/LockableItem.h"
#include "DataModel/ObjectIdentifier.h"
#include "DataModel/Serializable.h"
#include "DataTypes.h"
#include "Logger/Logger.h"
class Manager;
namespace DataModel
{
class Relation : protected Serializable, public LockableItem
{
public:
enum Type : unsigned char
{
TypeCalculate = 0,
TypeLocoSlave = (ObjectTypeLoco << 3), // not used anymore, TypeMultipeUnitSlave instead
TypeTrackSignal = (ObjectTypeTrack << 3),
TypeFeedbackAtSet = ObjectTypeFeedback << 3,
TypeFeedbackAtUnset = (ObjectTypeFeedback << 3) + 1,
TypeRouteAtLock = (ObjectTypeRoute << 3),
TypeRouteAtUnlock = (ObjectTypeRoute << 3) + 1,
TypeClusterTrack = (ObjectTypeCluster << 3),
TypeMultipleUnitSlave = (ObjectTypeMultipleUnit << 3),
};
typedef unsigned short Data;
static const Data DefaultData = 0;
inline Relation(Manager* manager,
const ObjectIdentifier& object1,
const ObjectIdentifier& object2,
const Type type,
const Priority priority = 0,
const unsigned short data = 0)
: manager(manager),
object1(object1),
object2(object2),
type(type),
priority(priority),
data(data)
{
}
inline Relation(Manager* manager,
const std::string& serialized)
: manager(manager),
data(0)
{
Deserialize(serialized);
}
virtual ~Relation()
{
}
virtual std::string Serialize() const override;
virtual bool Deserialize(const std::string& serialized) override;
inline ObjectID ObjectID1() const
{
return object1.GetObjectID();
}
inline void ObjectID1(ObjectID objectID1)
{
object1.SetObjectID(objectID1);
}
inline ObjectType ObjectType2() const
{
return object2.GetObjectType();
}
inline ObjectID ObjectID2() const
{
return object2.GetObjectID();
}
inline ObjectIdentifier ObjectIdentifier2() const
{
return object2;
}
LockableItem* GetObject2();
inline Type GetType() const
{
return type;
}
inline Priority GetPriority() const
{
return priority;
}
inline Data GetData() const
{
return data;
}
inline bool CompareObject2(const ObjectIdentifier& identifier) const
{
return object2 == identifier;
}
bool Reserve(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier) override;
bool Lock(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier) override;
bool Release(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier) override;
bool Execute(Logger::Logger* logger, const ObjectIdentifier& locoBaseIdentifier, const Delay delay);
private:
inline ObjectType ObjectType1() const
{
return object1.GetObjectType();
}
Manager* manager;
ObjectIdentifier object1;
ObjectIdentifier object2;
Type type;
Priority priority;
Data data;
};
} // namespace DataModel
railcontrol-23+dfsg1/DataModel/Route.cpp 0000664 0000000 0000000 00000026112 14751611131 0020266 0 ustar 00root root 0000000 0000000 /*
RailControl - Model Railway Control Software
Copyright (c) 2017-2023 Dominik (Teddy) Mahrer - www.railcontrol.org
RailControl 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 3, or (at your option) any
later version.
RailControl 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 RailControl; see the file LICENCE. If not see
.
*/
#include
#include
#include
#include "DataModel/LocoBase.h"
#include "DataModel/Relation.h"
#include "DataModel/Route.h"
#include "Manager.h"
#include "Utils/Utils.h"
using std::map;
using std::string;
using std::to_string;
namespace DataModel
{
Route::Route(Manager* manager, const std::string& serialized)
: LockableItem(),
manager(manager),
executeAtUnlock(false)
{
Deserialize(serialized);
Track* track = manager->GetTrack(fromTrack);
if (track == nullptr)
{
return;
}
track->AddRoute(this);
}
std::string Route::Serialize() const
{
std::string str;
str = "objectType=Route;";
str += LayoutItem::Serialize();
str += ";" + LockableItem::Serialize();
str += ";delay=" + to_string(delay);
str += ";lastused=" + to_string(lastUsed);
str += ";counter=" + to_string(counter);
str += ";automode=" + to_string(automode);
if (automode == AutomodeNo)
{
return str;
}
str += ";fromTrack=" + to_string(fromTrack);
str += ";fromorientation=" + to_string(fromOrientation);
str += ";toTrack=" + to_string(toTrack);
str += ";toorientation=" + to_string(toOrientation);
str += ";speed=" + to_string(speed);
str += ";feedbackIdReduced=" + to_string(feedbackIdReduced);
str += ";feedbackIdCreep=" + to_string(feedbackIdCreep);
str += ";feedbackIdStop=" + to_string(feedbackIdStop);
str += ";feedbackIdOver=" + to_string(feedbackIdOver);
str += ";pushpull=" + to_string(pushpull);
str += ";propulsion=" + to_string(propulsion);
str += ";traintype=" + to_string(trainType);
str += ";mintrainlength=" + to_string(minTrainLength);
str += ";maxtrainlength=" + to_string(maxTrainLength);
str += ";waitafterrelease=" + to_string(waitAfterRelease);
return str;
}
bool Route::Deserialize(const std::string& serialized)
{
map arguments;
ParseArguments(serialized, arguments);
string objectType = Utils::Utils::GetStringMapEntry(arguments, "objectType");
if (objectType.compare("Route") != 0)
{
return false;
}
LayoutItem::Deserialize(arguments);
LockableItem::Deserialize(arguments);
delay = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "delay", DefaultDelay));
lastUsed = Utils::Utils::GetIntegerMapEntry(arguments, "lastused", 0);
counter = Utils::Utils::GetIntegerMapEntry(arguments, "counter", 0);
automode = static_cast(Utils::Utils::GetBoolMapEntry(arguments, "automode", AutomodeNo));
if (automode == AutomodeNo)
{
fromTrack = TrackNone;
fromOrientation = OrientationRight;
toTrack = TrackNone;
toOrientation = OrientationRight;
speed = SpeedTravel;
feedbackIdReduced = FeedbackNone;
feedbackIdCreep = FeedbackNone;
feedbackIdStop = FeedbackNone;
feedbackIdOver = FeedbackNone;
pushpull = PushpullTypeBoth;
propulsion = PropulsionAll;
trainType = TrainTypeAll;
minTrainLength = 0;
maxTrainLength = 0;
waitAfterRelease = 0;
return true;
}
fromTrack = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "fromTrack", TrackNone));
fromOrientation = static_cast(Utils::Utils::GetBoolMapEntry(arguments, "fromorientation", OrientationRight));
toTrack = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "toTrack", TrackNone));
toOrientation = static_cast(Utils::Utils::GetBoolMapEntry(arguments, "toorientation", OrientationRight));
speed = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "speed", SpeedTravel));
feedbackIdReduced = Utils::Utils::GetIntegerMapEntry(arguments, "feedbackIdReduced", FeedbackNone);
feedbackIdCreep = Utils::Utils::GetIntegerMapEntry(arguments, "feedbackIdCreep", FeedbackNone);
feedbackIdStop = Utils::Utils::GetIntegerMapEntry(arguments, "feedbackIdStop", FeedbackNone);
feedbackIdOver = Utils::Utils::GetIntegerMapEntry(arguments, "feedbackIdOver", FeedbackNone);
pushpull = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "pushpull", PushpullTypeBoth));
propulsion = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "propulsion", propulsion));
trainType = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "traintype", trainType));
minTrainLength = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "mintrainlength", 0));
maxTrainLength = static_cast(Utils::Utils::GetIntegerMapEntry(arguments, "maxtrainlength", 0));
waitAfterRelease = Utils::Utils::GetIntegerMapEntry(arguments, "waitafterrelease", 0);
return true;
}
void Route::DeleteRelations(std::vector& relations)
{
while (!relations.empty())
{
delete relations.back();
relations.pop_back();
}
}
bool Route::AssignRelations(std::vector& relations, const std::vector& newRelations)
{
std::lock_guard