Added enum property values support

Dieser Commit ist enthalten in:
Reinder Feenstra 2020-08-06 22:48:43 +02:00
Ursprung 5be0bedd3d
Commit 09a6503eb0
87 geänderte Dateien mit 1186 neuen und 1180 gelöschten Zeilen

Datei anzeigen

@ -31,6 +31,7 @@
#include "method.hpp"
#include "tablemodel.hpp"
#include <traintastic/enum/interfaceitemtype.hpp>
#include <traintastic/enum/attributetype.hpp>
#include <traintastic/locale/locale.hpp>
//#include <enum/valuetype.hpp>
//#include <enum/propertyflags.hpp>
@ -371,8 +372,14 @@ ObjectPtr Connection::readObject(const Message& message)
{
message.readBlock(); // item
const AttributeName attributeName = message.read<AttributeName>();
const ValueType type = message.read<ValueType>();
switch(message.read<AttributeType>())
{
case AttributeType::Value:
{
QVariant value;
switch(message.read<ValueType>())
switch(type)
{
case ValueType::Boolean:
value = message.read<bool>();
@ -393,13 +400,59 @@ ObjectPtr Connection::readObject(const Message& message)
case ValueType::Object:
case ValueType::Invalid:
default:
Q_ASSERT(false);
break;
}
if(Q_LIKELY(value.isValid()))
item->m_attributes[attributeName] = value;
break;
}
case AttributeType::Values:
{
const int length = message.read<int>(); // read uint32_t as int, Qt uses int for length
QList<QVariant> values;
switch(type)
{
case ValueType::Boolean:
{
for(int i = 0; i < length; i++)
values.append(message.read<bool>());
break;
}
case ValueType::Enum:
case ValueType::Integer:
{
for(int i = 0; i < length; i++)
values.append(message.read<qint64>());
break;
}
case ValueType::Float:
{
for(int i = 0; i < length; i++)
values.append(message.read<double>());
break;
}
case ValueType::String:
{
for(int i = 0; i < length; i++)
values.append(QString::fromUtf8(message.read<QByteArray>()));
break;
}
case ValueType::Object:
case ValueType::Invalid:
default:
Q_ASSERT(false);
break;
}
if(Q_LIKELY(values.length() == length))
item->m_attributes[attributeName] = values;
break;
}
default:
Q_ASSERT(false);
}
message.readBlockEnd(); // end attribute
}
message.readBlockEnd(); // end attributes

Datei anzeigen

@ -0,0 +1,46 @@
/**
* client/src/utils/internalupdateholder.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_CLIENT_UTILS_INTERNALUPDATEHOLDER_HPP
#define TRAINTASTIC_CLIENT_UTILS_INTERNALUPDATEHOLDER_HPP
class InternalUpdateHolder
{
private:
bool& m_value;
public:
inline InternalUpdateHolder(bool& value) :
m_value{value}
{
Q_ASSERT(!m_value);
m_value = true;
}
inline ~InternalUpdateHolder()
{
Q_ASSERT(m_value);
m_value = false;
}
};
#endif

Datei anzeigen

@ -0,0 +1,56 @@
/**
* client/src/utils/translateenum.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "translateenum.hpp"
#include <traintastic/locale/locale.hpp>
#include <traintastic/enum/decoderprotocol.hpp>
#include <traintastic/enum/direction.hpp>
#include <traintastic/enum/lengthunit.hpp>
#include <traintastic/enum/loconetcommandstation.hpp>
#include <traintastic/enum/loconetserialinterface.hpp>
#include <traintastic/enum/serialflowcontrol.hpp>
#include <traintastic/enum/speedunit.hpp>
#include <traintastic/enum/weightunit.hpp>
#include <traintastic/enum/worldscale.hpp>
#include <traintastic/enum/xpressnetcommandstation.hpp>
#include <traintastic/enum/xpressnetserialinterface.hpp>
#define TRANSLATE_ENUM(_type) \
if(enumName == EnumName<_type>::value) \
{ return Locale::tr(enumName + ":" + EnumValues<_type>::value.at(static_cast<_type>(value))); } \
else
QString translateEnum(const QString& enumName, qint64 value)
{
TRANSLATE_ENUM(DecoderProtocol)
TRANSLATE_ENUM(Direction)
TRANSLATE_ENUM(LengthUnit)
TRANSLATE_ENUM(LocoNetCommandStation)
TRANSLATE_ENUM(LocoNetSerialInterface)
TRANSLATE_ENUM(SerialFlowControl)
TRANSLATE_ENUM(SpeedUnit)
TRANSLATE_ENUM(WeightUnit)
TRANSLATE_ENUM(WorldScale)
TRANSLATE_ENUM(XpressNetCommandStation)
TRANSLATE_ENUM(XpressNetSerialInterface)
return enumName + "@" + QString::number(value);
}

Datei anzeigen

@ -0,0 +1,31 @@
/**
* client/src/utils/translateenum.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_CLIENT_UTILS_TRANSLATEENUM_HPP
#define TRAINTASTIC_CLIENT_UTILS_TRANSLATEENUM_HPP
#include <QString>
QString translateEnum(const QString& enumName, qint64 value);
#endif

Datei anzeigen

@ -22,26 +22,7 @@
#include "propertycheckbox.hpp"
#include "../network/property.hpp"
class InternalUpdateHolder
{
private:
bool& m_value;
public:
inline InternalUpdateHolder(bool& value) :
m_value{value}
{
Q_ASSERT(!m_value);
m_value = true;
}
inline ~InternalUpdateHolder()
{
Q_ASSERT(m_value);
m_value = false;
}
};
#include "../utils/internalupdateholder.hpp"
PropertyCheckBox::PropertyCheckBox(Property& property, QWidget* parent) :
QCheckBox(parent),

Datei anzeigen

@ -22,21 +22,25 @@
#include "propertycombobox.hpp"
#include "../network/property.hpp"
#include "../utils/internalupdateholder.hpp"
#include "../utils/translateenum.hpp"
PropertyComboBox::PropertyComboBox(Property& property, QWidget* parent) :
QComboBox(parent),
m_property{property}
m_property{property},
m_internalUpdate{false}
{
Q_ASSERT(m_property.type() == ValueType::Enum);
setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true));
setVisible(m_property.getAttributeBool(AttributeName::Visible, true));
//setChecked(m_property.toBool());
//connect(&m_property, &Property::valueChangedBool,
// [this](bool value)
// {
// InternalUpdateHolder hold(m_internalUpdate);
// setChecked(value);
// });
connect(&m_property, &Property::valueChangedInt64,
[this](qint64 value)
{
InternalUpdateHolder hold(m_internalUpdate);
if(int index = findData(value); index != -1)
setCurrentIndex(index);
});
connect(&m_property, &Property::attributeChanged,
[this](AttributeName name, const QVariant& value)
{
@ -50,14 +54,43 @@ PropertyComboBox::PropertyComboBox(Property& property, QWidget* parent) :
setVisible(value.toBool());
break;
case AttributeName::Values:
updateValues();
break;
default:
break;
}
});
//connect(this, &PropertyCheckBox::toggled,
// [this](bool value)
// {
// if(!m_internalUpdate)
// m_property.setValueBool(value);
// });
connect(this, static_cast<void(PropertyComboBox::*)(int)>(&PropertyComboBox::currentIndexChanged),
[this](int)
{
if(!m_internalUpdate)
if(QVariant v = currentData(); v.canConvert<int>())
m_property.setValueInt(v.toInt());
});
updateValues();
}
void PropertyComboBox::updateValues()
{
Q_ASSERT(m_property.type() == ValueType::Enum);
QVariant values = m_property.getAttribute(AttributeName::Values, QVariant());
if(Q_LIKELY(values.isValid()))
{
InternalUpdateHolder hold(m_internalUpdate);//QSignalBlocker block(this);
clear();
if(Q_LIKELY(values.userType() == QMetaType::QVariantList))
{
for(QVariant& v : values.toList())
{
const qint64 value = v.toLongLong();
addItem(translateEnum(m_property.enumName(), value), value);
if(m_property.toInt64() == value)
setCurrentIndex(count() - 1);
}
}
}
}

Datei anzeigen

@ -29,8 +29,13 @@ class Property;
class PropertyComboBox : public QComboBox
{
Q_OBJECT
protected:
Property& m_property;
bool m_internalUpdate;
void updateValues();
public:
PropertyComboBox(Property& property, QWidget* parent = nullptr);

Datei anzeigen

@ -13,6 +13,7 @@ greaterThan(QT_MINOR_VERSION, 11): { # >= 5.12
INCLUDEPATH += \
../shared/src \
../server/thirdparty \
thirdparty
SOURCES += \
@ -51,7 +52,8 @@ SOURCES += \
src/network/connection.cpp \
src/mdiarea.cpp \
src/network/method.cpp \
src/dialog/worldlistdialog.cpp
src/dialog/worldlistdialog.cpp \
src/utils/translateenum.cpp
HEADERS += \
src/mainwindow.hpp \
@ -93,7 +95,9 @@ HEADERS += \
src/network/connection.hpp \
src/mdiarea.hpp \
src/network/method.hpp \
src/dialog/worldlistdialog.hpp
src/dialog/worldlistdialog.hpp \
src/utils/translateenum.hpp \
src/utils/internalupdateholder.hpp
RESOURCES += \
dark.qrc

Datei anzeigen

@ -1,19 +1,19 @@
## Traintastic language file: English (US)
:address=Address
:baudrate=Baudrate
:command_station=Command station
:controllers=Controllers
:decoders=Decoders
:emergency_stop=Emergency stop
:id=Id
:loconet=LocoNet
:name=Name
:notes=Notes
:track_power=Track power
:online=Online
:port=Port
:track_power=Track power
:xpressnet=XpressNet
:loconet=LocoNet
:baudrate=Baudrate
:decoders=Decoders
clock:day=Day
clock:hour=Hour
@ -22,48 +22,71 @@ clock:month=Month
clock:multiplier=Multiplier
clock:year=Year
command_station.loconet_serial:flow_control=Flow control
command_station.loconet_serial:interface=Interface
command_station.z21:filtered_main_current=Filtered main current
command_station.z21:firmware_version=Firmware version
command_station.z21:hardware_type=Hardware type
command_station.z21:high_temperature=High temperature
command_station.z21:hostname=Hostname
command_station.z21:main_current=Main current
command_station.z21:power_lost=Power lost
command_station.z21:prog_current=Prog current
command_station.z21:programming_mode_active=Programming mode active
command_station.z21:serial_number=Serial number
command_station.z21:short_circuit=Short circuit
command_station.z21:short_circut_external=Short circut external
command_station.z21:short_circut_internal=Short circut internal
command_station.z21:supply_voltage=Supply voltage
command_station.z21:temperature=Temperature
command_station.z21:vcc_voltage=VCC voltage
command_station_list:add=Add
command_station_list:remove=Remove
console:level=Level
console:message=Message
console:object=Object
console:time=Time
controller.z21_app:active=Active
controller:active=Active
controller_list:add=Add
decoder:direction=Direction
decoder:functions=Functions
decoder:long_address=Long address
decoder:protocol=Protocol
decoder:speed_step=Speed step
decoder:speed_steps=Speed steps
decoder_function:id=Id
decoder_function:momentary=Momentary
decoder_function:number=Number
decoder_function:value=Value
decoder_function_list:add=Add function
decoder_function_list:f_hash=F#
decoder_list:add=Add
hardware.command_station.z21:filtered_main_current=Filtered main current
hardware.command_station.z21:firmware_version=Firmware version
hardware.command_station.z21:hardware_type=Hardware type
hardware.command_station.z21:high_temperature=High temperature
hardware.command_station.z21:hostname=Hostname
hardware.command_station.z21:main_current=Main current
hardware.command_station.z21:power_lost=Power lost
hardware.command_station.z21:prog_current=Prog current
hardware.command_station.z21:programming_mode_active=Programming mode active
hardware.command_station.z21:serial_number=Serial number
hardware.command_station.z21:short_circuit=Short circuit
hardware.command_station.z21:short_circut_external=Short circut external
hardware.command_station.z21:short_circut_internal=Short circut internal
hardware.command_station.z21:supply_voltage=Supply voltage
hardware.command_station.z21:temperature=Temperature
hardware.command_station.z21:vcc_voltage=VCC voltage
hardware.controller.z21_app:active=Active
hardware.controller:active=Active
hardware.decoder:direction=Direction
hardware.decoder:functions=Functions
hardware.decoder:protocol=Protocol
hardware.decoder:speed_step=Speed step
hardware.decoder:speed_steps=Speed steps
hardware.decoder_function:id=Id
hardware.decoder_function:momentary=Momentary
hardware.decoder_function:number=Number
hardware.decoder_function:value=Value
hardware.decoder_function_list:f_hash=F#
language:de-de=German
language:en-us=English (US)
language:nl-nl=Dutch
list.train:add=Create train
loconet_command_station:custom=Custom
loconet_command_station:digikeijs_dr5000=Digikeijs DR5000
loconet_command_station:uhlenbrock_intellibox=Uhlenbrock Intellibox
loconet_serial_interface:custom=Custom
loconet_serial_interface:digikeijs_dr5000=Digikeijs DR5000
loconet_serial_interface:rosoft_loconet_interface=RoSoft LocoNet interface
lua.script:active=Active
lua.script:code=Code
@ -102,15 +125,22 @@ qtapp.mainmenu:settings=Settings
qtapp.mainmenu:tools=Tools
qtapp.mainmenu:view=View
qtapp.world_list_dialog:world_list=World list
qtapp.world_list_dialog:load=Load
qtapp.world_list_dialog:cancel=Cancel
world_list:uuid=UUID
qtapp.world_list_dialog:load=Load
qtapp.world_list_dialog:world_list=World list
serial_flow_control:hardware=Hardware
serial_flow_control:none=None
settings:default_world=Default world
settings:localhost_only=Localhost only
settings:port=Port
train:lob=LOB
train:speed=Speed
train:throttle_speed=Throttle speed
train:weight=Weight
world:clock=Clock
world:command_stations=Command stations
world:decoders=Decoders
@ -118,21 +148,15 @@ world:edit=Edit world
world:emergency_stop=Emergency stop
world:inputs=Inputs
world:lua_scripts=Lua scripts
world:rail_vehicles=Rail vehicles
world:scale=Scale
world:track_power_off=Track power off
world:track_power_on=Track power on
world:rail_vehicles=Rail vehicles
console:message=Message
console:time=Time
console:level=Level
console:object=Object
world:trains=Trains
list.train:add=Create train
train:lob=LOB
train:speed=Speed
world_list:uuid=UUID
#! Garbage
#! Garbage
train:speedMax=Maximum speed
train:throttle_speed=Throttle speed
train:weight=Weight

Datei anzeigen

@ -32,6 +32,8 @@ hardware.decoder:speed_steps=Snelheid stappen
hardware.decoder_function:number=Nummer
hardware.decoder_function:value=Waarde
hardware.decoder_function_list:f_hash=F#
language:de-de=Duits
language:en-us=Engels (VS)
language:nl-nl=Nederlands
@ -53,7 +55,6 @@ qtapp.connect_dialog:server=Server
qtapp.connect_dialog:username=Gebruikersnaam
qtapp.mainmenu:about=Over
qtapp.mainmenu:settings=Instellingen
qtapp.mainmenu:connect_to_server=Verbind met server
qtapp.mainmenu:disconnect_from_server=Verbreek verbinding met server
qtapp.mainmenu:export_world=Wereld exporteren
@ -69,6 +70,7 @@ qtapp.mainmenu:quit=Afsluiten
qtapp.mainmenu:save_world=Wereld opslaan
qtapp.mainmenu:server_console=Server console
qtapp.mainmenu:server_settings=Server instellingen
qtapp.mainmenu:settings=Instellingen
qtapp.mainmenu:tools=Extra
qtapp.mainmenu:view=Beeld
@ -83,10 +85,3 @@ world:lua_scripts=Lua scripts
world:scale=Schaal
world:track_power_off=Railspanning uit
world:track_power_on=Railspanning aan
hardware.decoder_function_list:f_hash=F#

Datei anzeigen

@ -24,7 +24,20 @@ WeightProperty
- decoder2
# train
- trothlle speed
- weight simulation: 0=off, 1=real, 2=half
# netwerk
enum als string over netwerk?? nummers zijn dan alleen intern, niet in json/netwerk
# controller usb xpressnet interface
- allow estop
- allow power off
- mode:
- direct: multimaus decoder addr == decoder addr
- virtual decoder: multimaus decoder addr = assigend decoder addr
- virtual maus: multimaus addr = assigend decoder addr
# task thread

Datei anzeigen

@ -24,10 +24,10 @@
#include "interfaceitem.hpp"
#include "object.hpp"
AbstractAttribute::AbstractAttribute(InterfaceItem& item, AttributeName name, ValueType type) :
m_item{item},
m_name{name},
m_type{type}
AbstractAttribute::AbstractAttribute(InterfaceItem& _item, AttributeName _name, ValueType _type) :
m_item{_item},
m_name{_name},
m_type{_type}
{
}

Datei anzeigen

@ -39,16 +39,12 @@ class AbstractAttribute
void changed();
public:
AbstractAttribute(InterfaceItem& item, AttributeName name, ValueType type);
AbstractAttribute(InterfaceItem& _item, AttributeName _name, ValueType _type);
virtual ~AbstractAttribute() = default;
inline InterfaceItem& item() const { return m_item; }
inline AttributeName name() const { return m_name; }
inline ValueType type() const { return m_type; }
virtual bool toBool() const = 0;
virtual int64_t toInt64() const = 0;
virtual double toDouble() const = 0;
virtual std::string toString() const = 0;
};
#endif

Datei anzeigen

@ -28,7 +28,7 @@
#include <traintastic/enum/propertyflags.hpp>
#include "objectptr.hpp"
#include <cassert>
#include <nlohmann/json.hpp>
#include "../utils/json.hpp"
class AbstractProperty : public InterfaceItem
{

Datei anzeigen

@ -0,0 +1,42 @@
/**
* server/src/core/abstractvalueattribute.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_CORE_ABSTRACTVALUEATTRIBUTE_HPP
#define TRAINTASTIC_SERVER_CORE_ABSTRACTVALUEATTRIBUTE_HPP
#include "abstractattribute.hpp"
class AbstractValueAttribute : public AbstractAttribute
{
public:
AbstractValueAttribute(InterfaceItem& _item, AttributeName _name, ValueType _type) :
AbstractAttribute(_item, _name, _type)
{
}
virtual bool toBool() const = 0;
virtual int64_t toInt64() const = 0;
virtual double toDouble() const = 0;
virtual std::string toString() const = 0;
};
#endif

Datei anzeigen

@ -0,0 +1,44 @@
/**
* server/src/core/abstractvaluesattribute.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_CORE_ABSTRACTVALUESATTRIBUTE_HPP
#define TRAINTASTIC_SERVER_CORE_ABSTRACTVALUESATTRIBUTE_HPP
#include "abstractattribute.hpp"
class AbstractValuesAttribute : public AbstractAttribute
{
public:
AbstractValuesAttribute(InterfaceItem& _item, AttributeName _name, ValueType _type) :
AbstractAttribute(_item, _name, _type)
{
}
virtual uint32_t length() const = 0;
virtual bool getBool(uint32_t index) const = 0;
virtual int64_t getInt64(uint32_t index) const = 0;
virtual double getDouble(uint32_t index) const = 0;
virtual std::string getString(uint32_t index) const = 0;
};
#endif

Datei anzeigen

@ -0,0 +1,74 @@
/**
* server/src/core/arrayattribute.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_CORE_ARRAYATTRIBUTE_HPP
#define TRAINTASTIC_SERVER_CORE_ARRAYATTRIBUTE_HPP
#include <array>
#include "abstractvaluesattribute.hpp"
#include "to.hpp"
template<typename T, size_t N>
class ArrayAttribute : public AbstractValuesAttribute
{
protected:
const std::array<T, N>& m_values;
public:
ArrayAttribute(InterfaceItem& _item, AttributeName _name, const std::array<T, N>& values) :
AbstractValuesAttribute(_item, _name, value_type_v<T>),
m_values{values}
{
static_assert(value_type_v<T> != ValueType::Invalid);
}
virtual uint32_t length() const final
{
return m_values.size();
}
virtual bool getBool(uint32_t index) const final
{
assert(index < length());
return to<bool>(m_values[index]);
}
virtual int64_t getInt64(uint32_t index) const final
{
assert(index < length());
return to<int64_t>(m_values[index]);
}
virtual double getDouble(uint32_t index) const final
{
assert(index < length());
return to<double>(m_values[index]);
}
virtual std::string getString(uint32_t index) const final
{
assert(index < length());
return to<std::string>(m_values[index]);
}
};
#endif

Datei anzeigen

@ -23,21 +23,22 @@
#ifndef TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP
#define TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP
#include "abstractattribute.hpp"
#include "abstractvalueattribute.hpp"
#include "to.hpp"
#include "valuetypetraits.hpp"
template<typename T>
class Attribute : public AbstractAttribute
class Attribute : public AbstractValueAttribute
{
protected:
T m_value;
public:
Attribute(InterfaceItem& item, AttributeName name, const T& value) :
AbstractAttribute{item, name, value_type_v<T>},
AbstractValueAttribute{item, name, value_type_v<T>},
m_value{value}
{
static_assert(value_type_v<T> != ValueType::Invalid);
}
bool toBool() const final

Datei anzeigen

@ -0,0 +1,64 @@
/**
* server/src/core/attributes.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_CORE_ATTRIBUTES_HPP
#define TRAINTASTIC_SERVER_CORE_ATTRIBUTES_HPP
#include "interfaceitem.hpp"
struct Attributes
{
static inline void addCategory(InterfaceItem& item, Category value)
{
item.addAttribute(AttributeName::Category, value);
}
static inline void addEnabled(InterfaceItem& item, bool value)
{
item.addAttribute(AttributeName::Enabled, value);
}
static inline void addVisible(InterfaceItem& item, bool value)
{
item.addAttribute(AttributeName::Visible, value);
}
static inline void addObjectEditor(InterfaceItem& item, bool value)
{
item.addAttribute(AttributeName::ObjectEditor, value);
}
template<typename T, size_t N>
static inline void addValues(Property<T>& property, const std::array<T, N>& values)
{
property.addAttribute(AttributeName::Values, values);
}
//inline InterfaceItem& addAttributeSubObject(bool value) { return addAttribute(AttributeName::SubObject, value); }
/*
template<typename T, std::size_t N>
inline InterfaceItem& addAttributeValues(const std::array<T, N>& values) { return addAttribute(AttributeName::Values, values); }
*/
};
#endif

Datei anzeigen

@ -21,7 +21,8 @@
#include "idobject.hpp"
#include "traintastic.hpp"
#include "console.hpp"
#include "../world/world.hpp"
#include "../world/getworld.hpp"
#include "attributes.hpp"
IdObject::IdObject(const std::weak_ptr<World>& world, std::string_view _id) :
Object{},
@ -29,7 +30,10 @@ IdObject::IdObject(const std::weak_ptr<World>& world, std::string_view _id) :
id{this, "id", std::string(_id.data(), _id.size()), PropertyFlags::ReadWrite | PropertyFlags::Store, nullptr,
[this](std::string& value)
{
auto& m = Traintastic::instance->world->m_objects;
auto w = getWorld(this);
if(!w)
return false;
auto& m = w->m_objects;
if(m.find(value) != m.end())
return false;
auto n = m.extract(id);
@ -41,8 +45,8 @@ IdObject::IdObject(const std::weak_ptr<World>& world, std::string_view _id) :
auto w = world.lock();
const bool editable = w && contains(w->state.value(), WorldState::Edit);
m_interfaceItems.add(id)
.addAttributeEnabled(editable);
Attributes::addEnabled(id, editable);
m_interfaceItems.add(id);
}
IdObject::~IdObject()

Datei anzeigen

@ -27,12 +27,15 @@
#include <string>
#include <memory>
#include "attribute.hpp"
#include "arrayattribute.hpp"
#include <traintastic/enum/category.hpp>
class Object;
class InterfaceItem
{
friend struct Attributes;
public:
using Attributes = std::unordered_map<AttributeName, std::unique_ptr<AbstractAttribute>>;
@ -42,10 +45,15 @@ class InterfaceItem
Attributes m_attributes;
template<typename T>
InterfaceItem& addAttribute(AttributeName name, const T& value)
void addAttribute(AttributeName name, const T& value)
{
m_attributes.emplace(name, std::make_unique<Attribute<T>>(*this, name, value));
return *this;
}
template<typename T, size_t N>
void addAttribute(AttributeName name, const std::array<T, N>& values)
{
m_attributes.emplace(name, std::make_unique<ArrayAttribute<T, N>>(*this, name, values));
}
template<typename T>
@ -80,15 +88,6 @@ class InterfaceItem
return m_attributes;
}
inline InterfaceItem& addAttributeCategory(Category value) { return addAttribute(AttributeName::Category, value); }
inline InterfaceItem& addAttributeEnabled(bool value) { return addAttribute(AttributeName::Enabled, value); }
inline InterfaceItem& addAttributeVisible(bool value) { return addAttribute(AttributeName::Visible, value); }
inline InterfaceItem& addAttributeObjectEditor(bool value) { return addAttribute(AttributeName::ObjectEditor, value); }
inline InterfaceItem& addAttributeSubObject(bool value) { return addAttribute(AttributeName::SubObject, value); }
template<typename T, std::size_t N>
inline InterfaceItem& addAttributeValues(const std::array<T, N>& values) { return addAttribute(AttributeName::Values, values); }
inline void setAttributeEnabled(bool value) { setAttribute(AttributeName::Enabled, value); }
};

Datei anzeigen

@ -24,22 +24,39 @@
#include "interfaceitem.hpp"
#include <algorithm>
#ifndef NDEBUG
#include "abstractproperty.hpp"
static void check(const InterfaceItem& item)
{
if(const AbstractProperty* property = dynamic_cast<const AbstractProperty*>(&item))
{
if(property->type() == ValueType::Enum)
assert(property->attributes().find(AttributeName::Values) != property->attributes().cend()); // enum property must have a Values attribute
}
}
#endif
InterfaceItem* InterfaceItems::find(const std::string& name) const
{
auto it = m_items.find(name);
return (it != m_items.end()) ? &it->second : nullptr;
}
InterfaceItem& InterfaceItems::add(InterfaceItem& item)
void InterfaceItems::add(InterfaceItem& item)
{
#ifndef NDEBUG
check(item);
#endif
m_items.emplace(item.name(), item);
m_itemOrder.push_back(item.name());
return item;
}
InterfaceItem& InterfaceItems::insertBefore(InterfaceItem& item, const InterfaceItem& before)
void InterfaceItems::insertBefore(InterfaceItem& item, const InterfaceItem& before)
{
#ifndef NDEBUG
check(item);
#endif
m_items.emplace(item.name(), item);
m_itemOrder.insert(std::find(m_itemOrder.begin(), m_itemOrder.end(), before.name()), item.name());
return item;
}

Datei anzeigen

@ -45,8 +45,8 @@ class InterfaceItems
InterfaceItem* find(const std::string& name) const;
InterfaceItem& add(InterfaceItem& item);
InterfaceItem& insertBefore(InterfaceItem& item, const InterfaceItem& before);
void add(InterfaceItem& item);
void insertBefore(InterfaceItem& item, const InterfaceItem& before);
inline InterfaceItem& operator[](const std::string& name) const { return m_items.at(name); }
};

Datei anzeigen

@ -26,8 +26,10 @@
#include "traintastic.hpp"
#include "client.hpp"
#include "abstractproperty.hpp"
#include "abstractattribute.hpp"
#include "abstractvalueattribute.hpp"
#include "abstractvaluesattribute.hpp"
#include <traintastic/enum/interfaceitemtype.hpp>
#include <traintastic/enum/attributetype.hpp>
#include "tablemodel.hpp"
#include "../world/world.hpp"
#include "idobject.hpp"
@ -434,31 +436,7 @@ void Session::writeObject(Message& message, const ObjectPtr& object)
{
const AbstractAttribute& attribute = *it.second;
message.writeBlock(); // attribute
message.write(attribute.name());
message.write(attribute.type());
switch(attribute.type())
{
case ValueType::Boolean:
message.write(attribute.toBool());
break;
case ValueType::Enum:
case ValueType::Integer:
message.write(attribute.toInt64());
break;
case ValueType::Float:
message.write(attribute.toDouble());
break;
case ValueType::String:
message.write(attribute.toString());
break;
default:
assert(false);
break;
}
writeAttribute(message, attribute);
message.writeBlockEnd(); // end attribute
}
@ -547,6 +525,8 @@ void Session::objectAttributeChanged(AbstractAttribute& attribute)
auto event = Message::newEvent(Message::Command::ObjectAttributeChanged);
event->write(m_handles.getHandle(attribute.item().object().shared_from_this()));
event->write(attribute.item().name());
writeAttribute(*event, attribute);
/*
event->write(attribute.name());
event->write(attribute.type());
switch(attribute.type())
@ -568,5 +548,74 @@ void Session::objectAttributeChanged(AbstractAttribute& attribute)
//event->write(attribute.toString());
break;
}
*/
m_client->sendMessage(std::move(event));
}
void Session::writeAttribute(Message& message , const AbstractAttribute& attribute)
{
message.write(attribute.name());
message.write(attribute.type());
if(const AbstractValueAttribute* valueAttribute = dynamic_cast<const AbstractValueAttribute*>(&attribute))
{
message.write(AttributeType::Value);
switch(attribute.type())
{
case ValueType::Boolean:
message.write(valueAttribute->toBool());
break;
case ValueType::Enum:
case ValueType::Integer:
message.write(valueAttribute->toInt64());
break;
case ValueType::Float:
message.write(valueAttribute->toDouble());
break;
case ValueType::String:
message.write(valueAttribute->toString());
break;
default:
assert(false);
break;
}
}
else if(const AbstractValuesAttribute* valuesAttributes = dynamic_cast<const AbstractValuesAttribute*>(&attribute))
{
const uint32_t length = valuesAttributes->length();
message.write(AttributeType::Values);
message.write(length);
switch(attribute.type())
{
case ValueType::Boolean:
for(uint32_t i = 0; i < length; i++)
message.write(valuesAttributes->getBool(i));
break;
case ValueType::Enum:
case ValueType::Integer:
for(uint32_t i = 0; i < length; i++)
message.write(valuesAttributes->getInt64(i));
break;
case ValueType::Float:
for(uint32_t i = 0; i < length; i++)
message.write(valuesAttributes->getDouble(i));
break;
case ValueType::String:
for(uint32_t i = 0; i < length; i++)
message.write(valuesAttributes->getString(i));
break;
default:
assert(false);
break;
}
}
else
assert(false);
}

Datei anzeigen

@ -39,6 +39,9 @@ class Session : public std::enable_shared_from_this<Session>
{
friend class Client;
private:
static void writeAttribute(Message& message , const AbstractAttribute& attribute);
protected:
using Handle = uint32_t;
using Handles = HandleList<Handle, ObjectPtr>;

Datei anzeigen

@ -27,7 +27,7 @@
#include <limits>
#include <stdexcept>
#include <cmath>
#include <nlohmann/json.hpp>
#include "../utils/json.hpp"
class not_writable_error : public std::runtime_error
{
@ -101,10 +101,15 @@ To to(const From& value)
}
else if constexpr(std::is_same_v<From, nlohmann::json>)
{
// if constexpr(std::is_same_v<To, bool>)
return value;//.get<To>();
if constexpr(std::is_enum_v<To>)
{
To e;
from_json(value, e);
return e;
}
else
return value;
}
throw conversion_error();
}

Datei anzeigen

@ -165,7 +165,7 @@ class UnitProperty : public AbstractProperty//InterfaceItem
void load(const nlohmann::json& value) final
{
m_value = to<T>(value["value"]);
m_unit = value["unit"];
from_json(value["unit"], m_unit);
}
void load(const ObjectPtr& value) final

Datei anzeigen

@ -31,16 +31,12 @@ template<typename T>
class VectorAttribute : public AbstractAttribute
{
protected:
std::vector<T> m_value;
std::vector<T> m_values;
public:
//dsjfnkjdnvjkdnkvjf
Attribute(InterfaceItem& item, AttributeName name, const T& value) :
VectorAttribute(InterfaceItem& item, AttributeName name, const T& values) :
AbstractAttribute{item, name, value_type_v<T>},
m_value{value}
m_value{values}
{
}

Datei anzeigen

@ -29,14 +29,6 @@
#include "../lua/enumvalues.hpp"
#endif
NLOHMANN_JSON_SERIALIZE_ENUM(CommandStationStatus,
{
{CommandStationStatus::Offline, "offline"},
{CommandStationStatus::Initializing, "initializing"},
{CommandStationStatus::Online, "online"},
{CommandStationStatus::Error, "error"},
})
#ifndef DISABLE_LUA_SCRIPTING
LUA_ENUM_VALUES(CommandStationStatus, 4,
{

Datei anzeigen

@ -29,12 +29,11 @@
#include "../lua/enumvalues.hpp"
#endif
NLOHMANN_JSON_SERIALIZE_ENUM(DecoderProtocol,
{
{DecoderProtocol::Auto, "AUTO"},
{DecoderProtocol::DCC, "DCC"},
{DecoderProtocol::Custom, "CUSTOM"},
})
inline constexpr std::array<DecoderProtocol, 3> DecoderProtocolValues{{
DecoderProtocol::Auto,
DecoderProtocol::DCC,
DecoderProtocol::Custom,
}};
#ifndef DISABLE_LUA_SCRIPTING
LUA_ENUM_VALUES(DecoderProtocol, 3,

Datei anzeigen

@ -29,11 +29,11 @@
#include "../lua/enumvalues.hpp"
#endif
NLOHMANN_JSON_SERIALIZE_ENUM(Direction,
{
{Direction::Forward, "forward"},
{Direction::Reverse, "reverse"},
})
inline constexpr std::array<Direction, 2> DirectionValues{{
Direction::Forward,
Direction::Reverse,
}};
#ifndef DISABLE_LUA_SCRIPTING
LUA_ENUM_VALUES(Direction, 2,

Datei anzeigen

@ -24,16 +24,6 @@
#define TRAINTASTIC_SERVER_ENUM_LENGTHUNIT_HPP
#include <traintastic/enum/lengthunit.hpp>
#include <nlohmann/json.hpp>
NLOHMANN_JSON_SERIALIZE_ENUM(LengthUnit,
{
{LengthUnit::Meter, "m"},
{LengthUnit::CentiMeter, "cm"},
{LengthUnit::MilliMeter, "mm"},
{LengthUnit::Yard, "yd"},
{LengthUnit::Foot, "ft"},
{LengthUnit::Inch, "in"},
})
//#include <nlohmann/json.hpp>
#endif

Datei anzeigen

@ -31,23 +31,16 @@
inline constexpr std::array<LocoNetCommandStation, 3> LocoNetCommandStationValues{{
LocoNetCommandStation::Custom,
LocoNetCommandStation::DigiKeijsDR5000,
LocoNetCommandStation::DigikeijsDR5000,
LocoNetCommandStation::UhlenbrockIntellibox,
}};
NLOHMANN_JSON_SERIALIZE_ENUM(LocoNetCommandStation,
{
{LocoNetCommandStation::Custom, "custom"},
{LocoNetCommandStation::UhlenbrockIntellibox, "uhlenbrock_intellibox"},
{LocoNetCommandStation::DigiKeijsDR5000, "digikeijs_dr5000"},
})
#ifndef DISABLE_LUA_SCRIPTING
LUA_ENUM_VALUES(LocoNetCommandStation, 3,
{
{LocoNetCommandStation::Custom, "CUSTOM"},
{LocoNetCommandStation::UhlenbrockIntellibox, "UHLENBROCK_INTELLIBOX"},
{LocoNetCommandStation::DigiKeijsDR5000, "DIGIKEIJS_DR5000"},
{LocoNetCommandStation::DigikeijsDR5000, "DIGIKEIJS_DR5000"},
})
#endif

Datei anzeigen

@ -31,22 +31,15 @@
inline constexpr std::array<LocoNetSerialInterface, 3> LocoNetSerialInterfaceValues{{
LocoNetSerialInterface::Custom,
LocoNetSerialInterface::DigiKeijsDR5000,
LocoNetSerialInterface::DigikeijsDR5000,
LocoNetSerialInterface::RoSoftLocoNetInterface,
}};
NLOHMANN_JSON_SERIALIZE_ENUM(LocoNetSerialInterface,
{
{LocoNetSerialInterface::Custom, "custom"},
{LocoNetSerialInterface::DigiKeijsDR5000, "digikeijs_dr5000"},
{LocoNetSerialInterface::RoSoftLocoNetInterface, "rosoft_loconet_interface"},
})
#ifndef DISABLE_LUA_SCRIPTING
LUA_ENUM_VALUES(LocoNetSerialInterface, 3,
{
{LocoNetSerialInterface::Custom, "CUSTOM"},
{LocoNetSerialInterface::DigiKeijsDR5000, "DIGIKEIJS_DR5000"},
{LocoNetSerialInterface::DigikeijsDR5000, "DIGIKEIJS_DR5000"},
{LocoNetSerialInterface::RoSoftLocoNetInterface, "ROSOFT_LOCONET_INTERFACE"},
})
#endif

Datei anzeigen

@ -34,12 +34,6 @@ inline constexpr std::array<SerialFlowControl, 2> SerialFlowControlValues{{
SerialFlowControl::Hardware,
}};
NLOHMANN_JSON_SERIALIZE_ENUM(SerialFlowControl,
{
{SerialFlowControl::None, "none"},
{SerialFlowControl::Hardware, "hardware"},
})
#ifndef DISABLE_LUA_SCRIPTING
LUA_ENUM_VALUES(SerialFlowControl, 2,
{

Datei anzeigen

@ -0,0 +1,36 @@
/**
* server/src/enum/worldscale.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_ENUM_WORLDSCALE_HPP
#define TRAINTASTIC_SERVER_ENUM_WORLDSCALE_HPP
#include <traintastic/enum/worldscale.hpp>
inline constexpr std::array<WorldScale, 5> WorldScaleValues{{
WorldScale::H0,
WorldScale::N,
WorldScale::TT,
WorldScale::Z,
WorldScale::Custom,
}};
#endif

Datei anzeigen

@ -24,18 +24,15 @@
#define TRAINTASTIC_SERVER_ENUM_XPRESSNETCOMMANDSTATION_HPP
#include <traintastic/enum/xpressnetcommandstation.hpp>
#include <nlohmann/json.hpp>
#ifndef DISABLE_LUA_SCRIPTING
#include "../lua/enumvalues.hpp"
#endif
inline constexpr std::array<XpressNetCommandStation, 2> XpressNetCommandStationValues{{XpressNetCommandStation::Custom, XpressNetCommandStation::Roco10764}};
NLOHMANN_JSON_SERIALIZE_ENUM(XpressNetCommandStation,
{
{XpressNetCommandStation::Custom, "custom"},
{XpressNetCommandStation::Roco10764, "roco_10764"},
})
inline constexpr std::array<XpressNetCommandStation, 3> XpressNetCommandStationValues{{
XpressNetCommandStation::Custom,
XpressNetCommandStation::Roco10764,
XpressNetCommandStation::DigikeijsDR5000,
}};
#ifndef DISABLE_LUA_SCRIPTING
LUA_ENUM_VALUES(XpressNetCommandStation, 2,

Datei anzeigen

@ -24,7 +24,6 @@
#define TRAINTASTIC_SERVER_ENUM_XPRESSNETSERIALINTERFACE_HPP
#include <traintastic/enum/xpressnetserialinterface.hpp>
#include <nlohmann/json.hpp>
inline constexpr std::array<XpressNetSerialInterface, 5> XpressNetSerialInterfaceValues{{
XpressNetSerialInterface::Custom,
@ -34,13 +33,4 @@ inline constexpr std::array<XpressNetSerialInterface, 5> XpressNetSerialInterfac
XpressNetSerialInterface::RoSoftS88XPressNetLI,
}};
NLOHMANN_JSON_SERIALIZE_ENUM(XpressNetSerialInterface,
{
{XpressNetSerialInterface::Custom, "custom"},
{XpressNetSerialInterface::LenzLI100, "lenz_li100"},
{XpressNetSerialInterface::LenzLI100F, "lenz_li100f"},
{XpressNetSerialInterface::LenzLI101F, "lenz_li101f"},
{XpressNetSerialInterface::RoSoftS88XPressNetLI, "rosoft_s88xpressnetli"},
})
#endif

Datei anzeigen

@ -27,6 +27,7 @@
#include "../../world/world.hpp"
#include "../decoder/decoder.hpp"
#include "../decoder/decoderlist.hpp"
#include "../../core/attributes.hpp"
CommandStation::CommandStation(const std::weak_ptr<World>& world, std::string_view _id) :
IdObject(world, _id),
@ -59,17 +60,21 @@ CommandStation::CommandStation(const std::weak_ptr<World>& world, std::string_vi
auto w = world.lock();
const bool editable = w && contains(w->state.value(), WorldState::Edit);
m_interfaceItems.add(name)
.addAttributeEnabled(editable);
Attributes::addEnabled(name, editable);
m_interfaceItems.add(name);
m_interfaceItems.add(online);
m_interfaceItems.insertBefore(emergencyStop, notes)
.addAttributeEnabled(editable)
.addAttributeObjectEditor(false);
m_interfaceItems.insertBefore(trackVoltageOff, notes)
.addAttributeEnabled(editable)
.addAttributeObjectEditor(false);
Attributes::addObjectEditor(emergencyStop, false);
m_interfaceItems.insertBefore(emergencyStop, notes);
Attributes::addObjectEditor(trackVoltageOff, false);
m_interfaceItems.insertBefore(trackVoltageOff, notes);
m_interfaceItems.add(decoders);
m_interfaceItems.add(controllers);
m_interfaceItems.add(notes);
}

Datei anzeigen

@ -25,6 +25,7 @@
#include "commandstations.hpp"
#include "../../world/world.hpp"
#include "../../world/getworld.hpp"
#include "../../core/attributes.hpp"
CommandStationList::CommandStationList(Object& _parent, const std::string& parentPropertyName) :
ObjectList<CommandStation>(_parent, parentPropertyName),
@ -47,10 +48,11 @@ CommandStationList::CommandStationList(Object& _parent, const std::string& paren
auto world = getWorld(&_parent);
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(add)
.addAttributeEnabled(editable);
m_interfaceItems.add(remove)
.addAttributeEnabled(editable);
Attributes::addEnabled(add, editable);
m_interfaceItems.add(add);
Attributes::addEnabled(remove, editable);
m_interfaceItems.add(remove);
}
TableModelPtr CommandStationList::getModel()

Datei anzeigen

@ -20,8 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_CREATE_HPP
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_CREATE_HPP
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_COMMANDSTATIONS_HPP
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_COMMANDSTATIONS_HPP
#include "commandstation.hpp"

Datei anzeigen

@ -21,9 +21,9 @@
*/
#include "loconetserial.hpp"
//#include "../../world/world.hpp"
#include "../../core/traintastic.hpp"
#include "../../core/eventloop.hpp"
#include "../../core/attributes.hpp"
LocoNetSerial::LocoNetSerial(const std::weak_ptr<World>& world, std::string_view _id) :
SerialCommandStation(world, _id),
@ -35,7 +35,7 @@ LocoNetSerial::LocoNetSerial(const std::weak_ptr<World>& world, std::string_view
case LocoNetSerialInterface::Custom:
break;
case LocoNetSerialInterface::DigiKeijsDR5000:
case LocoNetSerialInterface::DigikeijsDR5000:
baudrate = 115200;
flowControl = SerialFlowControl::Hardware;
break;
@ -51,31 +51,11 @@ LocoNetSerial::LocoNetSerial(const std::weak_ptr<World>& world, std::string_view
name = "LocoNet (serial)";
loconet.setValueInternal(std::make_shared<LocoNet::LocoNet>(*this, loconet.name(), std::bind(&LocoNetSerial::send, this, std::placeholders::_1)));
interface.addAttributeEnabled(!online);
Attributes::addEnabled(interface, !online);
Attributes::addValues(interface, LocoNetSerialInterfaceValues);
m_interfaceItems.insertBefore(interface, baudrate);
m_interfaceItems.insertBefore(loconet, notes);
}
/*
bool LocoNetSerial::setOnline(bool& value)
{
if(!m_serialPort.is_open() && value)
{
if(!start())
{
value = false;
return false;
}
m_readBufferOffset = 0;
read();
loconet->queryLocoSlots();
}
else if(m_serialPort.is_open() && !value)
stop();
return true;
}*/
void LocoNetSerial::emergencyStopChanged(bool value)
{
@ -115,6 +95,11 @@ bool LocoNetSerial::send(const LocoNet::Message& message)
return true;
}
void LocoNetSerial::started()
{
loconet->queryLocoSlots();
}
void LocoNetSerial::read()
{
m_serialPort.async_read_some(boost::asio::buffer(m_readBuffer.data() + m_readBufferOffset, m_readBuffer.size() - m_readBufferOffset),

Datei anzeigen

@ -26,8 +26,6 @@
#include "serialcommandstation.hpp"
#include "../protocol/loconet/loconet.hpp"
#include "../../enum/loconetserialinterface.hpp"
//#include "../../enum/serialflowcontrol.hpp"
//#include <boost/asio/serial_port.hpp>
class LocoNetSerial : public SerialCommandStation
{
@ -39,6 +37,7 @@ class LocoNetSerial : public SerialCommandStation
bool start();
void stop();
bool send(const LocoNet::Message& msg);
void started() final;
void read() final;
public:

Datei anzeigen

@ -1,370 +0,0 @@
/**
* server/src/hardware/commandstation/protocol/xpressnet.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* hardware/protocol/xpressnet.cpp - XpressNet protocol
*
* This file is part of the traintastic-server source code
*
* Copyright (C) 2019-2020 Reinder Feenstra <reinderfeenstra@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if 0
#include "xpressnet.hpp"
#include "../commandstation.hpp"
#include "../../decoder/decoder.hpp"
#include "../../decoder/decoderchangeflags.hpp"
#include "../../decoder/decoderfunction.hpp"
#include "../../../core/traintastic.hpp"
namespace Protocol {
inline void addressLowHigh(uint16_t address, uint8_t& addressLow, uint8_t& addressHigh)
{
addressLow = address & 0xff;
if(address <= 99)
addressHigh = 0x00;
else
addressHigh = (0xC0 | address >> 8);
}
struct EmergencyStopLocomotive
{
const uint8_t headerByte = 0x92;
uint8_t addressHigh;
uint8_t addressLow;
uint8_t checksum;
EmergencyStopLocomotive(uint16_t address)
{
addressLowHigh(address, addressLow, addressHigh);
}
} __attribute__((packed));
struct SpeedAndDirectionInstruction
{
const uint8_t headerByte = 0xE4;
uint8_t identification;
uint8_t addressHigh;
uint8_t addressLow;
uint8_t speedAndDirection;
uint8_t checksum;
SpeedAndDirectionInstruction(uint16_t address)
{
addressLowHigh(address, addressLow, addressHigh);
}
} __attribute__((packed));
struct FunctionInstructionGroup
{
const uint8_t headerByte = 0xE4;
uint8_t identification;
uint8_t addressHigh;
uint8_t addressLow;
uint8_t functions = 0x00;
uint8_t checksum;
FunctionInstructionGroup(uint8_t group, uint16_t address)
{
assert(group >= 1 && group <= 3);
identification = 0x1f + group;
addressLowHigh(address, addressLow, addressHigh);
}
} __attribute__((packed));
struct SetFunctionStateGroup
{
const uint8_t headerByte = 0xE4;
uint8_t identification;
uint8_t addressHigh;
uint8_t addressLow;
uint8_t state = 0x00;
uint8_t checksum;
SetFunctionStateGroup(uint8_t group, uint16_t address)
{
assert(group >= 1 && group <= 3);
identification = 0x23 + group;
addressLowHigh(address, addressLow, addressHigh);
}
} __attribute__((packed));
struct RocoSetFunctionStateF13F20
{
const uint8_t headerByte = 0xE4;
const uint8_t identification = 0xF3;
uint8_t addressHigh;
uint8_t addressLow;
uint8_t state = 0x00;
uint8_t checksum;
RocoSetFunctionStateF13F20(uint16_t address)
{
addressLowHigh(address, addressLow, addressHigh);
}
} __attribute__((packed));
XpressNet::XpressNet(const std::weak_ptr<World>& world, const std::string& id, std::function<void(const void*)>&& send) :
IdObject(world, id),
m_send{std::move(send)},
commandStation{this, "command_station", XpressNetCommandStation::Custom, PropertyFlags::ReadWrite},
useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite},
useRocoF13F20Command{this, "use_roco_f13_f20_command", false, PropertyFlags::ReadWrite}
{
assert(m_send);
m_interfaceItems.add(commandStation);
m_interfaceItems.add(useFunctionStateCommands);
}
bool XpressNet::isDecoderSupported(const Decoder& decoder) const
{
return
decoder.protocol == DecoderProtocol::DCC &&
decoder.address >= addressMin &&
decoder.address <= addressMax;
}
uint8_t XpressNet::calcChecksum(const void* cmd)
{
const uint8_t* p = static_cast<const uint8_t*>(cmd);
const int length = p[0] & 0x0f;
uint8_t checksum = p[0];
for(int i = 1; i <= length; i++)
checksum ^= p[i];
return checksum;
}
void XpressNet::sendEmergencyStop(const Decoder& decoder)
{
logDebug(id, "XpressNet::sendEmergencyStop");
EmergencyStopLocomotive cmd(decoder.address);
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendSpeedAndDirectionInstruction(const Decoder& decoder)
{
logDebug(id, "XpressNet::sendSpeedAndDirectionInstruction");
SpeedAndDirectionInstruction cmd(decoder.address);
assert(decoder.speedStep <= decoder.speedSteps);
switch(decoder.speedSteps)
{
case 14:
cmd.identification = 0x10;
if(decoder.emergencyStop)
cmd.speedAndDirection = 0x01;
else if(decoder.speedStep > 0)
cmd.speedAndDirection = decoder.speedStep + 1;
break;
case 27:
cmd.identification = 0x11;
if(decoder.emergencyStop)
cmd.speedAndDirection = 0x01;
else if(decoder.speedStep > 0)
{
const uint8_t speedStep = decoder.speedStep + 1;
cmd.speedAndDirection = ((speedStep & 0x01) << 4) | (speedStep >> 1);
}
break;
case 28:
cmd.identification = 0x12;
if(decoder.emergencyStop)
cmd.speedAndDirection = 0x01;
else if(decoder.speedStep > 0)
{
const uint8_t speedStep = decoder.speedStep + 1;
cmd.speedAndDirection = ((speedStep & 0x01) << 4) | (speedStep >> 1);
}
break;
case 126:
cmd.identification = 0x13;
if(decoder.emergencyStop)
cmd.speedAndDirection = 0x01;
else if(decoder.speedStep > 0)
cmd.speedAndDirection = decoder.speedStep + 1;
break;
}
if(decoder.direction == Direction::Forward)
cmd.speedAndDirection |= 0x80;
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendFunctionInstructionGroup1(const Decoder& decoder)
{
FunctionInstructionGroup cmd(1, decoder.address);
// FL/F0:
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(0);
if(f && f->value)
cmd.functions |= 0x10;
// F1 .. F4:
for(uint32_t i = 1; i <= 4; i++)
{
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(i);
if(f && f->value)
cmd.functions |= 1 << (i - 1);
}
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendFunctionInstructionGroup2(const Decoder& decoder)
{
FunctionInstructionGroup cmd(2, decoder.address);
// F5 .. F8:
for(uint32_t i = 5; i <= 8; i++)
{
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(i);
if(f && f->value)
cmd.functions |= 1 << (i - 5);
}
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendFunctionInstructionGroup3(const Decoder& decoder)
{
FunctionInstructionGroup cmd(3, decoder.address);
// F9 .. F12:
for(uint32_t i = 9; i <= 12; i++)
{
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(i);
if(f && f->value)
cmd.functions |= 1 << (i - 9);
}
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendSetFunctionStateGroup1(const Decoder& decoder)
{
SetFunctionStateGroup cmd(1, decoder.address);
// FL/F0:
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(0);
if(f && f->momentary)
cmd.state |= 0x10;
// F1 .. F4:
for(uint32_t i = 1; i <= 4; i++)
{
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(i);
if(f && f->momentary)
cmd.state |= 1 << (i - 1);
}
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendSetFunctionStateGroup2(const Decoder& decoder)
{
SetFunctionStateGroup cmd(2, decoder.address);
// F5 .. F8:
for(uint32_t i = 5; i <= 8; i++)
{
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(i);
if(f && f->momentary)
cmd.state |= 1 << (i - 5);
}
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendSetFunctionStateGroup3(const Decoder& decoder)
{
SetFunctionStateGroup cmd(3, decoder.address);
// F9 .. F12:
for(uint32_t i = 9; i <= 12; i++)
{
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(i);
if(f && f->momentary)
cmd.state |= 1 << (i - 9);
}
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
void XpressNet::sendRocoSetFunctionStateF13F20(const Decoder& decoder)
{
RocoSetFunctionStateF13F20 cmd(decoder.address);
// F13 .. F20:
for(uint32_t i = 13; i <= 20; i++)
{
const std::shared_ptr<DecoderFunction>& f = decoder.getFunction(i);
if(f && f->value)
cmd.state |= 1 << (i - 13);
}
cmd.checksum = calcChecksum(&cmd);
m_send(&cmd);
}
}
#endif

Datei anzeigen

@ -1,76 +0,0 @@
/**
* server/src/hardware/commandstation/protocol/xpressnet.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#if 0//ndef SERVER_HARDWARE_COMMANDSTATION_PROTOCOL_XPRESSNET_HPP
#define SERVER_HARDWARE_COMMANDSTATION_PROTOCOL_XPRESSNET_HPP
#include "../../../core/idobject.hpp"
#include "../../../core/property.hpp"
#include "../../../enum/xpressnetcommandstation.hpp"
namespace Hardware {
class Decoder;
enum class DecoderChangeFlags;
namespace CommandStation::Protocol {
class XpressNet : public IdObject
{
protected:
static constexpr uint16_t addressMin = 1;
static constexpr uint16_t addressMax = 9999;
std::function<void(const void*)> m_send;
void sendEmergencyStop(const Decoder& decoder);
void sendSpeedAndDirectionInstruction(const Decoder& decoder);
void sendFunctionInstructionGroup1(const Decoder& decoder);
void sendFunctionInstructionGroup2(const Decoder& decoder);
void sendFunctionInstructionGroup3(const Decoder& decoder);
void sendSetFunctionStateGroup1(const Decoder& decoder);
void sendSetFunctionStateGroup2(const Decoder& decoder);
void sendSetFunctionStateGroup3(const Decoder& decoder);
void sendRocoSetFunctionStateF13F20(const Decoder& decoder);
public:
CLASS_ID("command_station.protocol.xpressnet")
static uint8_t calcChecksum(const void* cmd);
Property<XpressNetCommandStation> commandStation;
Property<bool> useFunctionStateCommands;
Property<bool> useRocoF13F20Command;
XpressNet(const std::weak_ptr<World>& world, const std::string& id, std::function<void(const void*)>&& send);
bool isDecoderSupported(const Decoder& decoder) const;
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber);
};
} }
#endif

Datei anzeigen

@ -24,6 +24,7 @@
#include "../../core/traintastic.hpp"
#include "../../world/world.hpp"
#include "../../core/eventloop.hpp"
#include "../../core/attributes.hpp"
#include "../decoder/decoderchangeflags.hpp"
#include "../protocol/xpressnet/messages.hpp"
#include "../protocol/z21.hpp"
@ -87,41 +88,41 @@ RocoZ21::RocoZ21(const std::weak_ptr<World>& world, std::string_view _id) :
return false;
}));
m_interfaceItems.insertBefore(hostname, notes)
.addAttributeEnabled(true);
m_interfaceItems.insertBefore(port, notes)
.addAttributeEnabled(true);
Attributes::addEnabled(hostname, true);
m_interfaceItems.insertBefore(hostname, notes);
Attributes::addEnabled(port, true);
m_interfaceItems.insertBefore(port, notes);
m_interfaceItems.insertBefore(loconet, notes);
m_interfaceItems.insertBefore(serialNumber, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(hardwareType, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(firmwareVersion, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(mainCurrent, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(progCurrent, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(filteredMainCurrent, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(temperature, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(supplyVoltage, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(vccVoltage, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(shortCircuit, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(programmingModeActive, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(highTemperature, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(powerLost, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(shortCircutInternal, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(shortCircutExternal, notes)
.addAttributeCategory(Category::Info);
Attributes::addCategory(serialNumber, Category::Info);
m_interfaceItems.insertBefore(serialNumber, notes);
Attributes::addCategory(hardwareType, Category::Info);
m_interfaceItems.insertBefore(hardwareType, notes);
Attributes::addCategory(firmwareVersion, Category::Info);
m_interfaceItems.insertBefore(firmwareVersion, notes);
Attributes::addCategory(mainCurrent, Category::Info);
m_interfaceItems.insertBefore(mainCurrent, notes);
Attributes::addCategory(progCurrent, Category::Info);
m_interfaceItems.insertBefore(progCurrent, notes);
Attributes::addCategory(filteredMainCurrent, Category::Info);
m_interfaceItems.insertBefore(filteredMainCurrent, notes);
Attributes::addCategory(temperature, Category::Info);
m_interfaceItems.insertBefore(temperature, notes);
Attributes::addCategory(firmwareVersion, Category::Info);
m_interfaceItems.insertBefore(supplyVoltage, notes);
Attributes::addCategory(vccVoltage, Category::Info);
m_interfaceItems.insertBefore(vccVoltage, notes);
Attributes::addCategory(firmwareVersion, Category::Info);
m_interfaceItems.insertBefore(shortCircuit, notes);
Attributes::addCategory(programmingModeActive, Category::Info);
m_interfaceItems.insertBefore(programmingModeActive, notes);
Attributes::addCategory(highTemperature, Category::Info);
m_interfaceItems.insertBefore(highTemperature, notes);
Attributes::addCategory(powerLost, Category::Info);
m_interfaceItems.insertBefore(powerLost, notes);
Attributes::addCategory(shortCircutInternal, Category::Info);
m_interfaceItems.insertBefore(shortCircutInternal, notes);
Attributes::addCategory(shortCircutExternal, Category::Info);
m_interfaceItems.insertBefore(shortCircutExternal, notes);
}
void RocoZ21::emergencyStopChanged(bool value)

Datei anzeigen

@ -20,8 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_Z21_HPP
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_Z21_HPP
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_ROCOZ21_HPP
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_ROCOZ21_HPP
#include "commandstation.hpp"
#include <boost/asio.hpp>

Datei anzeigen

@ -23,6 +23,7 @@
#include "serialcommandstation.hpp"
#include "../../core/traintastic.hpp"
#include "../../core/eventloop.hpp"
#include "../../core/attributes.hpp"
SerialCommandStation::SerialCommandStation(const std::weak_ptr<World>& world, std::string_view _id) :
CommandStation(world, _id),
@ -40,12 +41,12 @@ SerialCommandStation::SerialCommandStation(const std::weak_ptr<World>& world, st
//interface = LocoNetSerialInterface::Custom;
}}
{
port.addAttributeEnabled(!online);
baudrate.addAttributeEnabled(!online);
flowControl.addAttributeEnabled(!online);
Attributes::addEnabled(port, !online);
m_interfaceItems.insertBefore(port, notes);
Attributes::addEnabled(baudrate, !online);
m_interfaceItems.insertBefore(baudrate, notes);
Attributes::addEnabled(flowControl, !online);
Attributes::addValues(flowControl, SerialFlowControlValues);
m_interfaceItems.insertBefore(flowControl, notes);
}
@ -60,8 +61,6 @@ bool SerialCommandStation::setOnline(bool& value)
}
m_readBufferOffset = 0;
read();
//loconet->queryLocoSlots();
}
else if(m_serialPort.is_open() && !value)
stop();

Datei anzeigen

@ -38,6 +38,8 @@ class SerialCommandStation : public CommandStation
bool start();
void stop();
virtual void started() {}
virtual void read() = 0;
public:

Datei anzeigen

@ -1,223 +0,0 @@
/**
* server/src/hardware/commandstation/xpressnet/xpressnet.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xpressnet.hpp"
#include "../../../core/traintastic.hpp"
#include "../../decoder/decoder.hpp"
#include "../../decoder/decoderlist.hpp"
#include "../../decoder/decoderchangeflags.hpp"
namespace CommandStation {
XpressNet::XpressNet(const std::weak_ptr<World>& world, std::string_view _id) :
CommandStation(world, _id),
/*emergencyStop{this, "emergency_stop", false, PropertyFlags::ReadWrite | PropertyFlags::StoreState,
[this](bool value)
{
if(online)
{
if(value)
send(EmergencyStop());
else
send(NormalOperationResumed());
}
}},
trackVoltageOff{this, "track_voltage_off", false, PropertyFlags::ReadWrite | PropertyFlags::StoreState,
[this](bool value)
{
if(online)
{
if(value)
send(TrackPowerOff());
else
send(NormalOperationResumed());
}
}},*/
commandStation{this, "command_station", XpressNetCommandStation::Custom, PropertyFlags::ReadWrite,
[this](XpressNetCommandStation value)
{
switch(value)
{
case XpressNetCommandStation::Custom:
break;
case XpressNetCommandStation::Roco10764:
useEmergencyStopLocomotiveCommand.setValueInternal(false);
useFunctionStateCommands.setValueInternal(false);
useRocoF13F20Command.setValueInternal(true);
break;
}
}},
useEmergencyStopLocomotiveCommand{this, "use_emergency_stop_locomotive_command", false, PropertyFlags::ReadWrite,
[this](bool)
{
commandStation = XpressNetCommandStation::Custom;
}},
useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite,
[this](bool)
{
commandStation = XpressNetCommandStation::Custom;
}},
useRocoF13F20Command{this, "use_roco_f13_f20_command", false, PropertyFlags::ReadWrite,
[this](bool)
{
commandStation = XpressNetCommandStation::Custom;
}}
{
m_interfaceItems.add(emergencyStop)
.addAttributeObjectEditor(false);
m_interfaceItems.add(trackVoltageOff)
.addAttributeObjectEditor(false);
m_interfaceItems.insertBefore(commandStation, notes)
.addAttributeValues(XpressNetCommandStationValues)
.addAttributeCategory(Category::XpressNet)
.addAttributeEnabled(false);
m_interfaceItems.insertBefore(useEmergencyStopLocomotiveCommand, notes)
.addAttributeCategory(Category::XpressNet)
.addAttributeEnabled(false);
m_interfaceItems.insertBefore(useFunctionStateCommands, notes)
.addAttributeCategory(Category::XpressNet)
.addAttributeEnabled(false);
m_interfaceItems.insertBefore(useRocoF13F20Command, notes)
.addAttributeCategory(Category::XpressNet)
.addAttributeEnabled(false);
}
void XpressNet::worldEvent(WorldState state, WorldEvent event)
{
CommandStation::worldEvent(state, event);
commandStation.setAttributeEnabled(mode == TraintasticMode::Edit);
useEmergencyStopLocomotiveCommand.setAttributeEnabled(mode == TraintasticMode::Edit);
useFunctionStateCommands.setAttributeEnabled(mode == TraintasticMode::Edit);
useRocoF13F20Command.setAttributeEnabled(mode == TraintasticMode::Edit);
}
void XpressNet::decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber)
{
if(!online)
return;
logDebug(id, "XpressNet::decoderChanged");
if(useEmergencyStopLocomotiveCommand && changes == DecoderChangeFlags::EmergencyStop && decoder.emergencyStop)
send(EmergencyStopLocomotive(
decoder.address,
decoder.longAddress));
else if(has(changes, DecoderChangeFlags::EmergencyStop | DecoderChangeFlags::Direction | DecoderChangeFlags::SpeedStep | DecoderChangeFlags::SpeedSteps))
{
switch(decoder.speedSteps)
{
case 14:
send(SpeedAndDirectionInstruction14(
decoder.address,
decoder.longAddress,
decoder.emergencyStop,
decoder.direction,
decoder.speedStep,
getFunctionValue(decoder, 0)));
break;
case 27:
send(SpeedAndDirectionInstruction27(
decoder.address,
decoder.longAddress,
decoder.emergencyStop,
decoder.direction,
decoder.speedStep));
break;
case 28:
send(SpeedAndDirectionInstruction28(
decoder.address,
decoder.longAddress,
decoder.emergencyStop,
decoder.direction,
decoder.speedStep));
break;
case 126:
case 128:
send(SpeedAndDirectionInstruction128(
decoder.address,
decoder.longAddress,
decoder.emergencyStop,
decoder.direction,
decoder.speedStep));
break;
default:
logWarning((id, std::to_string(decoder.speedSteps) + " speed steps not supported");
break;
}
}
else if(has(changes, DecoderChangeFlags::FunctionValue))
{
if(functionNumber <= 4)
send(FunctionInstructionGroup1(
decoder.address,
decoder.longAddress,
getFunctionValue(decoder, 0),
getFunctionValue(decoder, 1),
getFunctionValue(decoder, 2),
getFunctionValue(decoder, 3),
getFunctionValue(decoder, 4)));
else if(functionNumber <= 8)
send(FunctionInstructionGroup2(
decoder.address,
decoder.longAddress,
getFunctionValue(decoder, 5),
getFunctionValue(decoder, 6),
getFunctionValue(decoder, 7),
getFunctionValue(decoder, 8)));
else if(functionNumber <= 12)
send(FunctionInstructionGroup3(
decoder.address,
decoder.longAddress,
getFunctionValue(decoder, 9),
getFunctionValue(decoder, 10),
getFunctionValue(decoder, 11),
getFunctionValue(decoder, 12)));
else if(useRocoF13F20Command && functionNumber <= 20)
send(Roco::FunctionInstructionF13F20(
decoder.address,
decoder.longAddress,
getFunctionValue(decoder, 13),
getFunctionValue(decoder, 14),
getFunctionValue(decoder, 15),
getFunctionValue(decoder, 16),
getFunctionValue(decoder, 17),
getFunctionValue(decoder, 18),
getFunctionValue(decoder, 19),
getFunctionValue(decoder, 20)));
else
logWarning((id, "Function F" + std::to_string(functionNumber) + " not supported");
}
}
bool XpressNet::getFunctionValue(const Decoder& decoder, uint32_t number)
{
const auto& f = decoder.getFunction(number);
return f && f->value;
}
}

Datei anzeigen

@ -1,54 +0,0 @@
/**
* server/src/hardware/commandstation/xpressnet/xpressnet.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_XPRESSNET_XPRESSNET_HPP
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_XPRESSNET_XPRESSNET_HPP
#include "../commandstation.hpp"
#include "../../protocol/xpressnet.hpp"
#include "../../../enum/xpressnetcommandstation.hpp"
namespace CommandStation {
class XpressNet : public CommandStation
{
protected:
static bool getFunctionValue(const Decoder& decoder, uint32_t number);
void worldEvent(WorldState state, WorldEvent event) override;
void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) override;
virtual void send(const Protocol::XpressNet::Message& msg) = 0;
public:
Property<XpressNetCommandStation> commandStation;
Property<bool> useEmergencyStopLocomotiveCommand;
Property<bool> useFunctionStateCommands;
Property<bool> useRocoF13F20Command;
XpressNet(const std::weak_ptr<World>& world, std::string_view _id);
};
}
#endif

Datei anzeigen

@ -24,6 +24,7 @@
#include "../../world/world.hpp"
#include "../../core/traintastic.hpp"
#include "../../core/eventloop.hpp"
#include "../../core/attributes.hpp"
XpressNetSerial::XpressNetSerial(const std::weak_ptr<World>& world, std::string_view _id) :
SerialCommandStation(world, _id),
@ -57,6 +58,7 @@ XpressNetSerial::XpressNetSerial(const std::weak_ptr<World>& world, std::string_
name = "XpressNet (serial)";
xpressnet.setValueInternal(std::make_shared<XpressNet::XpressNet>(*this, xpressnet.name(), std::bind(&XpressNetSerial::send, this, std::placeholders::_1)));
Attributes::addValues(interface, XpressNetSerialInterfaceValues);
m_interfaceItems.insertBefore(interface, baudrate);
m_interfaceItems.insertBefore(xpressnet, notes);
}

Datei anzeigen

@ -25,6 +25,7 @@
#include "controllerlisttablemodel.hpp"
#include "../commandstation/commandstation.hpp"
#include "../../world/getworld.hpp"
#include "../../core/attributes.hpp"
Controller::Controller(const std::weak_ptr<World>& _world, std::string_view _id) :
IdObject(_world, _id),
@ -51,8 +52,8 @@ Controller::Controller(const std::weak_ptr<World>& _world, std::string_view _id)
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(name);
m_interfaceItems.add(commandStation)
.addAttributeEnabled(editable);
Attributes::addEnabled(commandStation, editable);
m_interfaceItems.add(commandStation);
m_interfaceItems.add(active);
m_interfaceItems.add(notes);
}

Datei anzeigen

@ -25,6 +25,7 @@
#include "controllers.hpp"
#include "../commandstation/commandstation.hpp"
#include "../../world/getworld.hpp"
#include "../../core/attributes.hpp"
ControllerList::ControllerList(Object& _parent, const std::string& parentPropertyName) :
ObjectList<Controller>(_parent, parentPropertyName),
@ -45,8 +46,8 @@ ControllerList::ControllerList(Object& _parent, const std::string& parentPropert
auto world = getWorld(&_parent);
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(add)
.addAttributeEnabled(editable);
Attributes::addEnabled(add, editable);
m_interfaceItems.add(add);
}
TableModelPtr ControllerList::getModel()

Datei anzeigen

@ -27,6 +27,7 @@
#include "../decoder/decoder.hpp"
#include "../protocol/z21.hpp"
#include "../../utils/to_hex.hpp"
#include "../../core/attributes.hpp"
WLANmaus::WLANmaus(const std::weak_ptr<World> world, std::string_view _id) :
Controller(world, _id),
@ -34,8 +35,8 @@ WLANmaus::WLANmaus(const std::weak_ptr<World> world, std::string_view _id) :
m_blockLocoInfo{nullptr},
port{this, "port", 21105, PropertyFlags::ReadWrite | PropertyFlags::Store}
{
m_interfaceItems.add(port)
.addAttributeEnabled(!active);
Attributes::addEnabled(port, !active);
m_interfaceItems.add(port);
}
bool WLANmaus::setActive(bool& value)

Datei anzeigen

@ -28,6 +28,7 @@
#include "decoderfunctionlist.hpp"
#include "../../world/world.hpp"
#include "../commandstation/commandstation.hpp"
#include "../../core/attributes.hpp"
//constexpr uint16_t addressDCCMin = 1;
constexpr uint16_t addressDCCShortMax = 127;
@ -103,20 +104,22 @@ Decoder::Decoder(const std::weak_ptr<World>& world, std::string_view _id) :
//auto w = world.lock();
// const bool editable = w && contains(w->state.value(), WorldState::Edit) && speedStep == 0;
m_interfaceItems.add(name)
.addAttributeEnabled(false);
m_interfaceItems.add(commandStation)
.addAttributeEnabled(false);
m_interfaceItems.add(protocol)
.addAttributeEnabled(false);
m_interfaceItems.add(address)
.addAttributeEnabled(false);
m_interfaceItems.add(longAddress)
.addAttributeEnabled(false);
Attributes::addEnabled(name, false);
m_interfaceItems.add(name);
Attributes::addEnabled(commandStation, false);
m_interfaceItems.add(commandStation);
Attributes::addEnabled(protocol, false);
Attributes::addValues(protocol, DecoderProtocolValues);
m_interfaceItems.add(protocol);
Attributes::addEnabled(address, false);
m_interfaceItems.add(address);
Attributes::addEnabled(longAddress, false);
m_interfaceItems.add(longAddress);
m_interfaceItems.add(emergencyStop);
Attributes::addValues(direction, DirectionValues);
m_interfaceItems.add(direction);
m_interfaceItems.add(speedSteps)
.addAttributeEnabled(false);
Attributes::addEnabled(speedSteps, false);
m_interfaceItems.add(speedSteps);
m_interfaceItems.add(speedStep);
m_interfaceItems.add(functions);
m_interfaceItems.add(notes);

Datei anzeigen

@ -22,6 +22,7 @@
#include "decoder.hpp"
#include "decoderchangeflags.hpp"
#include "../../world/world.hpp"
#include "../../core/attributes.hpp"
const std::shared_ptr<DecoderFunction> DecoderFunction::null;
@ -41,10 +42,10 @@ DecoderFunction::DecoderFunction(Decoder& decoder, std::string_view _id) :
auto w = decoder.world().lock();
const bool editable = w && contains(w->state.value(), WorldState::Edit);
m_interfaceItems.add(number)
.addAttributeEnabled(editable);
m_interfaceItems.add(name)
.addAttributeEnabled(editable);
Attributes::addEnabled(number, editable);
m_interfaceItems.add(number);
Attributes::addEnabled(name, editable);
m_interfaceItems.add(name);
}
void DecoderFunction::worldEvent(WorldState state, WorldEvent event)

Datei anzeigen

@ -24,6 +24,7 @@
#include "decoderfunctionlisttablemodel.hpp"
#include "decoder.hpp"
#include "../../world/getworld.hpp"
#include "../../core/attributes.hpp"
DecoderFunctionList::DecoderFunctionList(Object& _parent, const std::string& parentPropertyName) :
ObjectList<DecoderFunction>(_parent, parentPropertyName),
@ -57,8 +58,8 @@ DecoderFunctionList::DecoderFunctionList(Object& _parent, const std::string& par
auto world = getWorld(&_parent);
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(add)
.addAttributeEnabled(editable);
Attributes::addEnabled(add, editable);
m_interfaceItems.add(add);
}
TableModelPtr DecoderFunctionList::getModel()

Datei anzeigen

@ -24,6 +24,7 @@
#include "decoderlisttablemodel.hpp"
#include "../commandstation/commandstation.hpp"
#include "../../world/getworld.hpp"
#include "../../core/attributes.hpp"
DecoderList::DecoderList(Object& _parent, const std::string& parentPropertyName) :
ObjectList<Decoder>(_parent, parentPropertyName),
@ -45,8 +46,8 @@ DecoderList::DecoderList(Object& _parent, const std::string& parentPropertyName)
auto world = getWorld(&_parent);
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(add)
.addAttributeEnabled(editable);
Attributes::addEnabled(add, editable);
m_interfaceItems.add(add);
}
TableModelPtr DecoderList::getModel()

Datei anzeigen

@ -21,6 +21,7 @@
*/
#include "loconetinput.hpp"
#include "../../core/attributes.hpp"
LocoNetInput::LocoNetInput(const std::weak_ptr<World> world, std::string_view _id) :
Input(world, _id),
@ -44,10 +45,10 @@ LocoNetInput::LocoNetInput(const std::weak_ptr<World> world, std::string_view _i
return false;
}}
{
m_interfaceItems.add(loconet)
.addAttributeEnabled(false);
m_interfaceItems.add(address)
.addAttributeEnabled(false);
Attributes::addEnabled(loconet, false);
m_interfaceItems.add(loconet);
Attributes::addEnabled(address, false);
m_interfaceItems.add(address);
}
void LocoNetInput::worldEvent(WorldState state, WorldEvent event)

Datei anzeigen

@ -27,6 +27,7 @@
#include "../../../core/traintastic.hpp"
#include "../../commandstation/commandstation.hpp"
#include "../../input/loconetinput.hpp"
#include "../../../core/attributes.hpp"
namespace LocoNet {
@ -44,9 +45,9 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu
SubObject(_parent, parentPropertyName),
m_commandStation{dynamic_cast<CommandStation*>(&_parent)},
m_send{std::move(send)},
m_debugLog{true/*false*/},
m_debugLog{false},
m_queryLocoSlots{SLOT_UNKNOWN},
commandStation{this, "command_station", LocoNetCommandStation::Custom, PropertyFlags::ReadWrite,
commandStation{this, "command_station", LocoNetCommandStation::Custom, PropertyFlags::ReadWrite | PropertyFlags::Store,
[this](LocoNetCommandStation value)
{
switch(value)
@ -54,7 +55,7 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu
case LocoNetCommandStation::Custom:
break;
case LocoNetCommandStation::DigiKeijsDR5000:
case LocoNetCommandStation::DigikeijsDR5000:
break;
case LocoNetCommandStation::UhlenbrockIntellibox:
@ -69,8 +70,9 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu
{
assert(m_send);
m_interfaceItems.add(commandStation)
.addAttributeEnabled(false);
Attributes::addEnabled(commandStation, m_commandStation && !m_commandStation->online);
Attributes::addValues(commandStation, LocoNetCommandStationValues);
m_interfaceItems.add(commandStation);
m_interfaceItems.add(debugLog);
}

Datei anzeigen

@ -24,6 +24,7 @@
#include "../../../core/traintastic.hpp"
#include "../../../core/eventloop.hpp"
#include "../../decoder/decoder.hpp"
#include "../../../core/attributes.hpp"
namespace XpressNet {
@ -42,21 +43,28 @@ XpressNet::XpressNet(Object& _parent, const std::string& parentPropertyName, std
case XpressNetCommandStation::Roco10764:
useEmergencyStopLocomotiveCommand.setValueInternal(false);
useFunctionStateCommands.setValueInternal(false);
//useFunctionStateCommands.setValueInternal(false);
useRocoF13F20Command.setValueInternal(true);
break;
case XpressNetCommandStation::DigikeijsDR5000:
useEmergencyStopLocomotiveCommand.setValueInternal(false); // ?????
//useFunctionStateCommands.setValueInternal(false);
useRocoF13F20Command.setValueInternal(true);
break;
}
// TODO: updateEnabled();
}},
useEmergencyStopLocomotiveCommand{this, "use_emergency_stop_locomotive_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
[this](bool)
{
commandStation = XpressNetCommandStation::Custom;
}},
useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
[this](bool)
{
commandStation = XpressNetCommandStation::Custom;
}},
//useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
// [this](bool)
// {
// commandStation = XpressNetCommandStation::Custom;
// }},
useRocoF13F20Command{this, "use_roco_f13_f20_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
[this](bool)
{
@ -68,14 +76,15 @@ XpressNet::XpressNet(Object& _parent, const std::string& parentPropertyName, std
m_debugLog = value;
}}
{
m_interfaceItems.add(commandStation)
.addAttributeEnabled(false);
m_interfaceItems.add(useEmergencyStopLocomotiveCommand)
.addAttributeEnabled(false);
m_interfaceItems.add(useFunctionStateCommands)
.addAttributeEnabled(false);
m_interfaceItems.add(useRocoF13F20Command)
.addAttributeEnabled(false);
Attributes::addEnabled(commandStation, false);
Attributes::addValues(commandStation, XpressNetCommandStationValues);
m_interfaceItems.add(commandStation);
Attributes::addEnabled(useEmergencyStopLocomotiveCommand, false);
m_interfaceItems.add(useEmergencyStopLocomotiveCommand);
//Attributes::addEnabled(useFunctionStateCommands, false);
//m_interfaceItems.add(useFunctionStateCommands);
Attributes::addEnabled(useRocoF13F20Command, false);
m_interfaceItems.add(useRocoF13F20Command);
}
void XpressNet::worldEvent(WorldState state, WorldEvent event)
@ -86,7 +95,7 @@ void XpressNet::worldEvent(WorldState state, WorldEvent event)
commandStation.setAttributeEnabled(editable);
useEmergencyStopLocomotiveCommand.setAttributeEnabled(editable);
useFunctionStateCommands.setAttributeEnabled(editable);
//useFunctionStateCommands.setAttributeEnabled(editable);
useRocoF13F20Command.setAttributeEnabled(editable);
}

Datei anzeigen

@ -50,7 +50,7 @@ class XpressNet : public SubObject
Property<XpressNetCommandStation> commandStation;
Property<bool> useEmergencyStopLocomotiveCommand;
Property<bool> useFunctionStateCommands;
//Property<bool> useFunctionStateCommands;
Property<bool> useRocoF13F20Command;
Property<bool> debugLog;

Datei anzeigen

@ -27,6 +27,7 @@
#include "../world/world.hpp"
#include "../enum/worldevent.hpp"
#include "../set/worldstate.hpp"
#include "../core/attributes.hpp"
namespace Lua {
@ -49,8 +50,8 @@ Script::Script(const std::weak_ptr<World>& world, std::string_view _id) :
m_interfaceItems.add(name);
m_interfaceItems.add(active);
m_interfaceItems.add(code)
.addAttributeEnabled(!active && editable);
Attributes::addEnabled(code, !active && editable);
m_interfaceItems.add(code);
}
void Script::addToWorld()

Datei anzeigen

@ -23,6 +23,7 @@
#include "scriptlist.hpp"
#include "scriptlisttablemodel.hpp"
#include "../world/getworld.hpp"
#include "../core/attributes.hpp"
namespace Lua {
@ -42,8 +43,8 @@ ScriptList::ScriptList(Object& _parent, const std::string& parentPropertyName) :
auto world = getWorld(&_parent);
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(add)
.addAttributeEnabled(editable);
Attributes::addEnabled(add, editable);
m_interfaceItems.add(add);
}
TableModelPtr ScriptList::getModel()

Datei anzeigen

@ -23,6 +23,7 @@
#include "train.hpp"
#include "../world/world.hpp"
#include "trainlisttablemodel.hpp"
#include "../core/attributes.hpp"
Train::Train(const std::weak_ptr<World>& world, std::string_view _id) :
IdObject(world, _id),
@ -37,13 +38,14 @@ Train::Train(const std::weak_ptr<World>& world, std::string_view _id) :
auto w = world.lock();
const bool editable = w && contains(w->state.value(), WorldState::Edit);
m_interfaceItems.add(name)
.addAttributeEnabled(editable);
Attributes::addEnabled(name, editable);
m_interfaceItems.add(name);
m_interfaceItems.add(lob);
Attributes::addValues(direction, DirectionValues);
m_interfaceItems.add(direction);
m_interfaceItems.add(speed);
m_interfaceItems.add(speedMax)
.addAttributeEnabled(editable);
Attributes::addEnabled(speedMax, editable);
m_interfaceItems.add(speedMax);
m_interfaceItems.add(throttleSpeed);
m_interfaceItems.add(weight);
}

Datei anzeigen

@ -24,6 +24,7 @@
#include "trainlisttablemodel.hpp"
#include "../world/world.hpp"
#include "../world/getworld.hpp"
#include "../core/attributes.hpp"
TrainList::TrainList(Object& _parent, const std::string& parentPropertyName) :
ObjectList<Train>(_parent, parentPropertyName),
@ -39,8 +40,8 @@ TrainList::TrainList(Object& _parent, const std::string& parentPropertyName) :
auto world = getWorld(&_parent);
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(add)
.addAttributeEnabled(editable);
Attributes::addEnabled(add, editable);
m_interfaceItems.add(add);
}
TableModelPtr TrainList::getModel()

60
server/src/utils/json.hpp Normale Datei
Datei anzeigen

@ -0,0 +1,60 @@
/**
* server/src/utils/json.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_UTILS_JSON_HPP
#define TRAINTASTIC_SERVER_UTILS_JSON_HPP
#include <nlohmann/json.hpp>
#include <traintastic/enum/enum.hpp>
#include <traintastic/set/set.hpp>
template<typename BasicJsonType, typename EnumType>
inline void to_json(const BasicJsonType& j, const EnumType& e, typename std::enable_if_t<std::is_enum_v<EnumType> && !is_set_v<EnumType>>* = nullptr)
{
e = EnumValues<EnumType>::value.at(e);
}
template<typename BasicJsonType, typename EnumType>
inline void from_json(const BasicJsonType& j, EnumType& e, typename std::enable_if_t<std::is_enum_v<EnumType> && !is_set_v<EnumType>>* = nullptr)
{
auto it = std::find_if(EnumValues<EnumType>::value.cbegin(), EnumValues<EnumType>::value.cend(),
[j](const auto& v)
{
return v.second == j;
});
e = it != EnumValues<EnumType>::value.cend() ? it->first : EnumValues<EnumType>::value.cbegin()->first;
}
template<typename BasicJsonType, typename EnumType>
inline void to_json(const BasicJsonType& j, const EnumType& e, typename std::enable_if_t<is_set_v<EnumType>>* = nullptr)
{
assert(false);
}
template<typename BasicJsonType, typename EnumType>
inline void from_json(const BasicJsonType& j, EnumType& e, typename std::enable_if_t<is_set_v<EnumType>>* = nullptr)
{
assert(false);
}
#endif

Datei anzeigen

@ -23,8 +23,8 @@
#include "railvehiclelist.hpp"
#include "railvehiclelisttablemodel.hpp"
#include "railvehicles.hpp"
#include "../../world/world.hpp"
#include "../../world/getworld.hpp"
#include "../../core/attributes.hpp"
RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPropertyName) :
ObjectList<RailVehicle>(_parent, parentPropertyName),
@ -40,8 +40,8 @@ RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPrope
auto world = getWorld(&_parent);
const bool editable = world && contains(world->state.value(), WorldState::Edit);
m_interfaceItems.add(add)
.addAttributeEnabled(editable);
Attributes::addEnabled(add, editable);
m_interfaceItems.add(add);
}
TableModelPtr RailVehicleList::getModel()

Datei anzeigen

@ -22,6 +22,7 @@
#include "vehicle.hpp"
#include "../world/world.hpp"
#include "../core/attributes.hpp"
Vehicle::Vehicle(const std::weak_ptr<World>& world, std::string_view _id) :
IdObject(world, _id),
@ -30,8 +31,8 @@ Vehicle::Vehicle(const std::weak_ptr<World>& world, std::string_view _id) :
auto w = world.lock();
const bool editable = w && contains(w->state.value(), WorldState::Edit);
m_interfaceItems.add(name)
.addAttributeEnabled(editable);
Attributes::addEnabled(name, editable);
m_interfaceItems.add(name);
}
void Vehicle::worldEvent(WorldState state, WorldEvent event)

Datei anzeigen

@ -28,6 +28,7 @@
#include "worldsaver.hpp"
#include "../core/traintastic.hpp"
#include "../core/objectlisttablemodel.hpp"
#include "../core/attributes.hpp"
using nlohmann::json;
@ -121,6 +122,7 @@ World::World(Private) :
m_filename = Traintastic::instance->worldDir() / to_string(m_uuid) / filename;
m_interfaceItems.add(name);
Attributes::addValues(scale, WorldScaleValues);
m_interfaceItems.add(scale);
m_interfaceItems.add(commandStations);

Datei anzeigen

@ -31,7 +31,7 @@
#include <boost/uuid/uuid.hpp>
#include <nlohmann/json.hpp>
#include <traintastic/enum/worldevent.hpp>
#include <traintastic/enum/worldscale.hpp>
#include "../enum/worldscale.hpp"
#include <traintastic/set/worldstate.hpp>
#include "../clock/clock.hpp"
#include "../hardware/commandstation/commandstationlist.hpp"

Datei anzeigen

@ -0,0 +1,34 @@
/**
* shared/src/traintastic/enum/attributetype.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ATTRIBUTETYPE_HPP
#define TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ATTRIBUTETYPE_HPP
#include <cstdint>
enum class AttributeType : uint8_t
{
Value = 1,
Values = 2,
};
#endif

Datei anzeigen

@ -40,4 +40,12 @@ struct EnumName<CommandStationStatus>
static constexpr char const* value = "command_station_status";
};
ENUM_VALUES(CommandStationStatus, 4,
{
{CommandStationStatus::Offline, "offline"},
{CommandStationStatus::Initializing, "initializing"},
{CommandStationStatus::Online, "online"},
{CommandStationStatus::Error, "error"},
})
#endif

Datei anzeigen

@ -30,10 +30,10 @@ enum class DecoderProtocol : uint8_t
{
Auto = 0,
DCC = 1,
Motorola = 2,
MFX = 3,
Selectrix = 4,
FMZ = 5,
//Motorola = 2,
//MFX = 3,
//Selectrix = 4,
//FMZ = 5,
Custom = 255,
};
@ -43,4 +43,11 @@ struct EnumName<DecoderProtocol>
static constexpr char const* value = "decoder_protocol";
};
ENUM_VALUES(DecoderProtocol, 3,
{
{DecoderProtocol::Auto, "AUTO"},
{DecoderProtocol::DCC, "DCC"},
{DecoderProtocol::Custom, "CUSTOM"},
})
#endif

Datei anzeigen

@ -38,4 +38,10 @@ struct EnumName<Direction>
static constexpr char const* value = "direction";
};
ENUM_VALUES(Direction, 2,
{
{Direction::Forward, "forward"},
{Direction::Reverse, "reverse"},
})
#endif

Datei anzeigen

@ -24,10 +24,32 @@
#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ENUM_HPP
#define TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ENUM_HPP
#include <frozen/map.h>
#define ENUM_NAME(_type, _name) \
template<> \
struct EnumName<_type> \
{ \
static constexpr char const* value = _name; \
};
#define ENUM_VALUES(_type, _size, ...) \
template<> \
struct EnumValues<_type> \
{ \
static constexpr frozen::map<_type, const char*, _size> value = { __VA_ARGS__ }; \
};
template<typename T>
struct EnumName
{
static_assert(sizeof(T) != sizeof(T), "template specialization required");
};
template<typename T>
struct EnumValues
{
static_assert(sizeof(T) != sizeof(T), "template specialization required");
};
#endif

Datei anzeigen

@ -41,4 +41,14 @@ struct EnumName<LengthUnit>
static constexpr char const* value = "length_unit";
};
ENUM_VALUES(LengthUnit, 6,
{
{LengthUnit::Meter, "m"},
{LengthUnit::CentiMeter, "cm"},
{LengthUnit::MilliMeter, "mm"},
{LengthUnit::Yard, "yd"},
{LengthUnit::Foot, "ft"},
{LengthUnit::Inch, "in"},
})
#endif

Datei anzeigen

@ -25,18 +25,22 @@
#include <cstdint>
#include "enum.hpp"
#include <frozen/map.h>
enum class LocoNetCommandStation : uint16_t
{
Custom = 0,
UhlenbrockIntellibox = 1,
DigiKeijsDR5000 = 2,
DigikeijsDR5000 = 2,
};
template<>
struct EnumName<LocoNetCommandStation>
ENUM_NAME(LocoNetCommandStation, "loconet_command_station")
ENUM_VALUES(LocoNetCommandStation, 3,
{
static constexpr char const* value = "loconet_command_station";
};
{LocoNetCommandStation::Custom, "custom"},
{LocoNetCommandStation::UhlenbrockIntellibox, "uhlenbrock_intellibox"},
{LocoNetCommandStation::DigikeijsDR5000, "digikeijs_dr5000"},
})
#endif

Datei anzeigen

@ -29,14 +29,17 @@
enum class LocoNetSerialInterface : uint16_t
{
Custom = 0,
DigiKeijsDR5000 = 1,
DigikeijsDR5000 = 1,
RoSoftLocoNetInterface = 2,
};
template<>
struct EnumName<LocoNetSerialInterface>
ENUM_NAME(LocoNetSerialInterface, "loconet_serial_interface")
ENUM_VALUES(LocoNetSerialInterface, 3,
{
static constexpr char const* value = "loconet_serial_interface";
};
{LocoNetSerialInterface::Custom, "custom"},
{LocoNetSerialInterface::DigikeijsDR5000, "digikeijs_dr5000"},
{LocoNetSerialInterface::RoSoftLocoNetInterface, "rosoft_loconet_interface"},
})
#endif

Datei anzeigen

@ -20,30 +20,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/**
* shared/src/enum/serialflowcontrol.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019-2020 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SHARED_ENUM_serialflowcontrol_HPP
#define traintastic_shared_enum_serialflowcontrol_hpp
#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_SERIALFLOWCONTROL_HPP
#define TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_SERIALFLOWCONTROL_HPP
#include <cstdint>
#include "enum.hpp"
@ -54,10 +32,12 @@ enum class SerialFlowControl : uint8_t
Hardware = 1,
};
template<>
struct EnumName<SerialFlowControl>
ENUM_NAME(SerialFlowControl, "serial_flow_control")
ENUM_VALUES(SerialFlowControl, 2,
{
static constexpr char const* value = "serial_flow_control";
};
{SerialFlowControl::None, "none"},
{SerialFlowControl::Hardware, "hardware"},
})
#endif

Datei anzeigen

@ -38,4 +38,11 @@ struct EnumName<SpeedUnit>
static constexpr char const* value = "speed_unit";
};
ENUM_VALUES(SpeedUnit, 3,
{
{SpeedUnit::MeterPerSecond, "mps"},
{SpeedUnit::KiloMeterPerHour, "kmph"},
{SpeedUnit::MilePerHour, "mph"},
})
#endif

Datei anzeigen

@ -39,4 +39,12 @@ struct EnumName<WeightUnit>
static constexpr char const* value = "weight_unit";
};
ENUM_VALUES(WeightUnit, 4,
{
{WeightUnit::KiloGram, "kg"},
{WeightUnit::Ton, "ton"},
{WeightUnit::ShortTons, "short_tons"},
{WeightUnit::LongTons, "long_tons"},
})
#endif

Datei anzeigen

@ -43,4 +43,15 @@ struct EnumName<WorldEvent>
static constexpr char const* value = "world_event";
};
ENUM_VALUES(WorldEvent, 7,
{
{WorldEvent::Stop, "stop"},
{WorldEvent::Run, "run"},
{WorldEvent::EditDisabled, "edit_disabled"},
{WorldEvent::EditEnabled, "edit_enabled"},
{WorldEvent::TrackPowerOff, "track_power_off"},
{WorldEvent::TrackPowerOn, "track_power_on"},
{WorldEvent::EmergencyStop, "emergency_stop"},
})
#endif

Datei anzeigen

@ -41,4 +41,13 @@ struct EnumName<WorldScale>
static constexpr char const* value = "world_scale";
};
ENUM_VALUES(WorldScale, 5,
{
{WorldScale::H0, "h0"},
{WorldScale::N, "n"},
{WorldScale::TT, "tt"},
{WorldScale::Z, "z"},
{WorldScale::Custom, "custom"},
})
#endif

Datei anzeigen

@ -30,6 +30,7 @@ enum class XpressNetCommandStation : uint16_t
{
Custom = 0,
Roco10764 = 1,
DigikeijsDR5000 = 2,
};
template<>
@ -38,4 +39,11 @@ struct EnumName<XpressNetCommandStation>
static constexpr char const* value = "xpressnet_command_station";
};
ENUM_VALUES(XpressNetCommandStation, 3,
{
{XpressNetCommandStation::Custom, "custom"},
{XpressNetCommandStation::Roco10764, "roco_10764"},
{XpressNetCommandStation::DigikeijsDR5000, "digikeijs_dr5000"},
})
#endif

Datei anzeigen

@ -41,4 +41,13 @@ struct EnumName<XpressNetSerialInterface>
static constexpr char const* value = "xpressnet_serial_interface";
};
ENUM_VALUES(XpressNetSerialInterface, 5,
{
{XpressNetSerialInterface::Custom, "custom"},
{XpressNetSerialInterface::LenzLI100, "lenz_li100"},
{XpressNetSerialInterface::LenzLI100F, "lenz_li100f"},
{XpressNetSerialInterface::LenzLI101F, "lenz_li101f"},
{XpressNetSerialInterface::RoSoftS88XPressNetLI, "rosoft_s88xpressnetli"},
})
#endif