Added enum property values support
Dieser Commit ist enthalten in:
Ursprung
5be0bedd3d
Commit
09a6503eb0
@ -31,6 +31,7 @@
|
|||||||
#include "method.hpp"
|
#include "method.hpp"
|
||||||
#include "tablemodel.hpp"
|
#include "tablemodel.hpp"
|
||||||
#include <traintastic/enum/interfaceitemtype.hpp>
|
#include <traintastic/enum/interfaceitemtype.hpp>
|
||||||
|
#include <traintastic/enum/attributetype.hpp>
|
||||||
#include <traintastic/locale/locale.hpp>
|
#include <traintastic/locale/locale.hpp>
|
||||||
//#include <enum/valuetype.hpp>
|
//#include <enum/valuetype.hpp>
|
||||||
//#include <enum/propertyflags.hpp>
|
//#include <enum/propertyflags.hpp>
|
||||||
@ -371,35 +372,87 @@ ObjectPtr Connection::readObject(const Message& message)
|
|||||||
{
|
{
|
||||||
message.readBlock(); // item
|
message.readBlock(); // item
|
||||||
const AttributeName attributeName = message.read<AttributeName>();
|
const AttributeName attributeName = message.read<AttributeName>();
|
||||||
QVariant value;
|
const ValueType type = message.read<ValueType>();
|
||||||
switch(message.read<ValueType>())
|
|
||||||
|
switch(message.read<AttributeType>())
|
||||||
{
|
{
|
||||||
case ValueType::Boolean:
|
case AttributeType::Value:
|
||||||
value = message.read<bool>();
|
{
|
||||||
break;
|
QVariant value;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case ValueType::Boolean:
|
||||||
|
value = message.read<bool>();
|
||||||
|
break;
|
||||||
|
|
||||||
case ValueType::Enum:
|
case ValueType::Enum:
|
||||||
case ValueType::Integer:
|
case ValueType::Integer:
|
||||||
value = message.read<qint64>();
|
value = message.read<qint64>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueType::Float:
|
case ValueType::Float:
|
||||||
value = message.read<double>();
|
value = message.read<double>();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueType::String:
|
case ValueType::String:
|
||||||
value = QString::fromUtf8(message.read<QByteArray>());
|
value = QString::fromUtf8(message.read<QByteArray>());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ValueType::Object:
|
case ValueType::Object:
|
||||||
case ValueType::Invalid:
|
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);
|
Q_ASSERT(false);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Q_LIKELY(value.isValid()))
|
|
||||||
item->m_attributes[attributeName] = value;
|
|
||||||
|
|
||||||
message.readBlockEnd(); // end attribute
|
message.readBlockEnd(); // end attribute
|
||||||
}
|
}
|
||||||
message.readBlockEnd(); // end attributes
|
message.readBlockEnd(); // end attributes
|
||||||
|
|||||||
46
client/src/utils/internalupdateholder.hpp
Normale Datei
46
client/src/utils/internalupdateholder.hpp
Normale Datei
@ -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
|
||||||
56
client/src/utils/translateenum.cpp
Normale Datei
56
client/src/utils/translateenum.cpp
Normale Datei
@ -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);
|
||||||
|
}
|
||||||
31
client/src/utils/translateenum.hpp
Normale Datei
31
client/src/utils/translateenum.hpp
Normale Datei
@ -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
|
||||||
@ -22,26 +22,7 @@
|
|||||||
|
|
||||||
#include "propertycheckbox.hpp"
|
#include "propertycheckbox.hpp"
|
||||||
#include "../network/property.hpp"
|
#include "../network/property.hpp"
|
||||||
|
#include "../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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
PropertyCheckBox::PropertyCheckBox(Property& property, QWidget* parent) :
|
PropertyCheckBox::PropertyCheckBox(Property& property, QWidget* parent) :
|
||||||
QCheckBox(parent),
|
QCheckBox(parent),
|
||||||
|
|||||||
@ -22,21 +22,25 @@
|
|||||||
|
|
||||||
#include "propertycombobox.hpp"
|
#include "propertycombobox.hpp"
|
||||||
#include "../network/property.hpp"
|
#include "../network/property.hpp"
|
||||||
|
#include "../utils/internalupdateholder.hpp"
|
||||||
|
#include "../utils/translateenum.hpp"
|
||||||
|
|
||||||
PropertyComboBox::PropertyComboBox(Property& property, QWidget* parent) :
|
PropertyComboBox::PropertyComboBox(Property& property, QWidget* parent) :
|
||||||
QComboBox(parent),
|
QComboBox(parent),
|
||||||
m_property{property}
|
m_property{property},
|
||||||
|
m_internalUpdate{false}
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_property.type() == ValueType::Enum);
|
Q_ASSERT(m_property.type() == ValueType::Enum);
|
||||||
setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true));
|
setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true));
|
||||||
setVisible(m_property.getAttributeBool(AttributeName::Visible, true));
|
setVisible(m_property.getAttributeBool(AttributeName::Visible, true));
|
||||||
//setChecked(m_property.toBool());
|
|
||||||
//connect(&m_property, &Property::valueChangedBool,
|
connect(&m_property, &Property::valueChangedInt64,
|
||||||
// [this](bool value)
|
[this](qint64 value)
|
||||||
// {
|
{
|
||||||
// InternalUpdateHolder hold(m_internalUpdate);
|
InternalUpdateHolder hold(m_internalUpdate);
|
||||||
// setChecked(value);
|
if(int index = findData(value); index != -1)
|
||||||
// });
|
setCurrentIndex(index);
|
||||||
|
});
|
||||||
connect(&m_property, &Property::attributeChanged,
|
connect(&m_property, &Property::attributeChanged,
|
||||||
[this](AttributeName name, const QVariant& value)
|
[this](AttributeName name, const QVariant& value)
|
||||||
{
|
{
|
||||||
@ -50,14 +54,43 @@ PropertyComboBox::PropertyComboBox(Property& property, QWidget* parent) :
|
|||||||
setVisible(value.toBool());
|
setVisible(value.toBool());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AttributeName::Values:
|
||||||
|
updateValues();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//connect(this, &PropertyCheckBox::toggled,
|
connect(this, static_cast<void(PropertyComboBox::*)(int)>(&PropertyComboBox::currentIndexChanged),
|
||||||
// [this](bool value)
|
[this](int)
|
||||||
// {
|
{
|
||||||
// if(!m_internalUpdate)
|
if(!m_internalUpdate)
|
||||||
// m_property.setValueBool(value);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,8 +29,13 @@ class Property;
|
|||||||
|
|
||||||
class PropertyComboBox : public QComboBox
|
class PropertyComboBox : public QComboBox
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Property& m_property;
|
Property& m_property;
|
||||||
|
bool m_internalUpdate;
|
||||||
|
|
||||||
|
void updateValues();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PropertyComboBox(Property& property, QWidget* parent = nullptr);
|
PropertyComboBox(Property& property, QWidget* parent = nullptr);
|
||||||
|
|||||||
@ -13,6 +13,7 @@ greaterThan(QT_MINOR_VERSION, 11): { # >= 5.12
|
|||||||
|
|
||||||
INCLUDEPATH += \
|
INCLUDEPATH += \
|
||||||
../shared/src \
|
../shared/src \
|
||||||
|
../server/thirdparty \
|
||||||
thirdparty
|
thirdparty
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@ -51,7 +52,8 @@ SOURCES += \
|
|||||||
src/network/connection.cpp \
|
src/network/connection.cpp \
|
||||||
src/mdiarea.cpp \
|
src/mdiarea.cpp \
|
||||||
src/network/method.cpp \
|
src/network/method.cpp \
|
||||||
src/dialog/worldlistdialog.cpp
|
src/dialog/worldlistdialog.cpp \
|
||||||
|
src/utils/translateenum.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/mainwindow.hpp \
|
src/mainwindow.hpp \
|
||||||
@ -93,7 +95,9 @@ HEADERS += \
|
|||||||
src/network/connection.hpp \
|
src/network/connection.hpp \
|
||||||
src/mdiarea.hpp \
|
src/mdiarea.hpp \
|
||||||
src/network/method.hpp \
|
src/network/method.hpp \
|
||||||
src/dialog/worldlistdialog.hpp
|
src/dialog/worldlistdialog.hpp \
|
||||||
|
src/utils/translateenum.hpp \
|
||||||
|
src/utils/internalupdateholder.hpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
dark.qrc
|
dark.qrc
|
||||||
|
|||||||
132
lang/en-us.txt
132
lang/en-us.txt
@ -1,19 +1,19 @@
|
|||||||
## Traintastic language file: English (US)
|
## Traintastic language file: English (US)
|
||||||
|
|
||||||
:address=Address
|
:address=Address
|
||||||
|
:baudrate=Baudrate
|
||||||
:command_station=Command station
|
:command_station=Command station
|
||||||
:controllers=Controllers
|
:controllers=Controllers
|
||||||
|
:decoders=Decoders
|
||||||
:emergency_stop=Emergency stop
|
:emergency_stop=Emergency stop
|
||||||
:id=Id
|
:id=Id
|
||||||
|
:loconet=LocoNet
|
||||||
:name=Name
|
:name=Name
|
||||||
:notes=Notes
|
:notes=Notes
|
||||||
:track_power=Track power
|
|
||||||
:online=Online
|
:online=Online
|
||||||
:port=Port
|
:port=Port
|
||||||
|
:track_power=Track power
|
||||||
:xpressnet=XpressNet
|
:xpressnet=XpressNet
|
||||||
:loconet=LocoNet
|
|
||||||
:baudrate=Baudrate
|
|
||||||
:decoders=Decoders
|
|
||||||
|
|
||||||
clock:day=Day
|
clock:day=Day
|
||||||
clock:hour=Hour
|
clock:hour=Hour
|
||||||
@ -22,48 +22,71 @@ clock:month=Month
|
|||||||
clock:multiplier=Multiplier
|
clock:multiplier=Multiplier
|
||||||
clock:year=Year
|
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:add=Add function
|
||||||
|
decoder_function_list:f_hash=F#
|
||||||
|
|
||||||
decoder_list:add=Add
|
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:de-de=German
|
||||||
language:en-us=English (US)
|
language:en-us=English (US)
|
||||||
language:nl-nl=Dutch
|
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:active=Active
|
||||||
lua.script:code=Code
|
lua.script:code=Code
|
||||||
|
|
||||||
@ -102,15 +125,22 @@ qtapp.mainmenu:settings=Settings
|
|||||||
qtapp.mainmenu:tools=Tools
|
qtapp.mainmenu:tools=Tools
|
||||||
qtapp.mainmenu:view=View
|
qtapp.mainmenu:view=View
|
||||||
|
|
||||||
qtapp.world_list_dialog:world_list=World list
|
|
||||||
qtapp.world_list_dialog:load=Load
|
|
||||||
qtapp.world_list_dialog:cancel=Cancel
|
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:default_world=Default world
|
||||||
settings:localhost_only=Localhost only
|
settings:localhost_only=Localhost only
|
||||||
settings:port=Port
|
settings:port=Port
|
||||||
|
|
||||||
|
train:lob=LOB
|
||||||
|
train:speed=Speed
|
||||||
|
train:throttle_speed=Throttle speed
|
||||||
|
train:weight=Weight
|
||||||
|
|
||||||
world:clock=Clock
|
world:clock=Clock
|
||||||
world:command_stations=Command stations
|
world:command_stations=Command stations
|
||||||
world:decoders=Decoders
|
world:decoders=Decoders
|
||||||
@ -118,21 +148,15 @@ world:edit=Edit world
|
|||||||
world:emergency_stop=Emergency stop
|
world:emergency_stop=Emergency stop
|
||||||
world:inputs=Inputs
|
world:inputs=Inputs
|
||||||
world:lua_scripts=Lua scripts
|
world:lua_scripts=Lua scripts
|
||||||
|
world:rail_vehicles=Rail vehicles
|
||||||
world:scale=Scale
|
world:scale=Scale
|
||||||
world:track_power_off=Track power off
|
world:track_power_off=Track power off
|
||||||
world:track_power_on=Track power on
|
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
|
world:trains=Trains
|
||||||
list.train:add=Create train
|
|
||||||
train:lob=LOB
|
world_list:uuid=UUID
|
||||||
train:speed=Speed
|
|
||||||
|
|
||||||
|
#! Garbage
|
||||||
|
#! Garbage
|
||||||
train:speedMax=Maximum speed
|
train:speedMax=Maximum speed
|
||||||
train:throttle_speed=Throttle speed
|
|
||||||
train:weight=Weight
|
|
||||||
|
|||||||
@ -32,6 +32,8 @@ hardware.decoder:speed_steps=Snelheid stappen
|
|||||||
hardware.decoder_function:number=Nummer
|
hardware.decoder_function:number=Nummer
|
||||||
hardware.decoder_function:value=Waarde
|
hardware.decoder_function:value=Waarde
|
||||||
|
|
||||||
|
hardware.decoder_function_list:f_hash=F#
|
||||||
|
|
||||||
language:de-de=Duits
|
language:de-de=Duits
|
||||||
language:en-us=Engels (VS)
|
language:en-us=Engels (VS)
|
||||||
language:nl-nl=Nederlands
|
language:nl-nl=Nederlands
|
||||||
@ -53,7 +55,6 @@ qtapp.connect_dialog:server=Server
|
|||||||
qtapp.connect_dialog:username=Gebruikersnaam
|
qtapp.connect_dialog:username=Gebruikersnaam
|
||||||
|
|
||||||
qtapp.mainmenu:about=Over
|
qtapp.mainmenu:about=Over
|
||||||
qtapp.mainmenu:settings=Instellingen
|
|
||||||
qtapp.mainmenu:connect_to_server=Verbind met server
|
qtapp.mainmenu:connect_to_server=Verbind met server
|
||||||
qtapp.mainmenu:disconnect_from_server=Verbreek verbinding met server
|
qtapp.mainmenu:disconnect_from_server=Verbreek verbinding met server
|
||||||
qtapp.mainmenu:export_world=Wereld exporteren
|
qtapp.mainmenu:export_world=Wereld exporteren
|
||||||
@ -69,6 +70,7 @@ qtapp.mainmenu:quit=Afsluiten
|
|||||||
qtapp.mainmenu:save_world=Wereld opslaan
|
qtapp.mainmenu:save_world=Wereld opslaan
|
||||||
qtapp.mainmenu:server_console=Server console
|
qtapp.mainmenu:server_console=Server console
|
||||||
qtapp.mainmenu:server_settings=Server instellingen
|
qtapp.mainmenu:server_settings=Server instellingen
|
||||||
|
qtapp.mainmenu:settings=Instellingen
|
||||||
qtapp.mainmenu:tools=Extra
|
qtapp.mainmenu:tools=Extra
|
||||||
qtapp.mainmenu:view=Beeld
|
qtapp.mainmenu:view=Beeld
|
||||||
|
|
||||||
@ -83,10 +85,3 @@ world:lua_scripts=Lua scripts
|
|||||||
world:scale=Schaal
|
world:scale=Schaal
|
||||||
world:track_power_off=Railspanning uit
|
world:track_power_off=Railspanning uit
|
||||||
world:track_power_on=Railspanning aan
|
world:track_power_on=Railspanning aan
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
hardware.decoder_function_list:f_hash=F#
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,20 @@ WeightProperty
|
|||||||
- decoder2
|
- 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
|
# task thread
|
||||||
|
|||||||
@ -24,10 +24,10 @@
|
|||||||
#include "interfaceitem.hpp"
|
#include "interfaceitem.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
AbstractAttribute::AbstractAttribute(InterfaceItem& item, AttributeName name, ValueType type) :
|
AbstractAttribute::AbstractAttribute(InterfaceItem& _item, AttributeName _name, ValueType _type) :
|
||||||
m_item{item},
|
m_item{_item},
|
||||||
m_name{name},
|
m_name{_name},
|
||||||
m_type{type}
|
m_type{_type}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,16 +39,12 @@ class AbstractAttribute
|
|||||||
void changed();
|
void changed();
|
||||||
|
|
||||||
public:
|
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 InterfaceItem& item() const { return m_item; }
|
||||||
inline AttributeName name() const { return m_name; }
|
inline AttributeName name() const { return m_name; }
|
||||||
inline ValueType type() const { return m_type; }
|
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
|
#endif
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
#include <traintastic/enum/propertyflags.hpp>
|
#include <traintastic/enum/propertyflags.hpp>
|
||||||
#include "objectptr.hpp"
|
#include "objectptr.hpp"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <nlohmann/json.hpp>
|
#include "../utils/json.hpp"
|
||||||
|
|
||||||
class AbstractProperty : public InterfaceItem
|
class AbstractProperty : public InterfaceItem
|
||||||
{
|
{
|
||||||
|
|||||||
42
server/src/core/abstractvalueattribute.hpp
Normale Datei
42
server/src/core/abstractvalueattribute.hpp
Normale Datei
@ -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
|
||||||
44
server/src/core/abstractvaluesattribute.hpp
Normale Datei
44
server/src/core/abstractvaluesattribute.hpp
Normale Datei
@ -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
|
||||||
74
server/src/core/arrayattribute.hpp
Normale Datei
74
server/src/core/arrayattribute.hpp
Normale Datei
@ -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
|
||||||
@ -23,21 +23,22 @@
|
|||||||
#ifndef TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP
|
#ifndef TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP
|
||||||
#define TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP
|
#define TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP
|
||||||
|
|
||||||
#include "abstractattribute.hpp"
|
#include "abstractvalueattribute.hpp"
|
||||||
#include "to.hpp"
|
#include "to.hpp"
|
||||||
#include "valuetypetraits.hpp"
|
#include "valuetypetraits.hpp"
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Attribute : public AbstractAttribute
|
class Attribute : public AbstractValueAttribute
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
T m_value;
|
T m_value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Attribute(InterfaceItem& item, AttributeName name, const T& value) :
|
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}
|
m_value{value}
|
||||||
{
|
{
|
||||||
|
static_assert(value_type_v<T> != ValueType::Invalid);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool toBool() const final
|
bool toBool() const final
|
||||||
|
|||||||
64
server/src/core/attributes.hpp
Normale Datei
64
server/src/core/attributes.hpp
Normale Datei
@ -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
|
||||||
@ -21,7 +21,8 @@
|
|||||||
#include "idobject.hpp"
|
#include "idobject.hpp"
|
||||||
#include "traintastic.hpp"
|
#include "traintastic.hpp"
|
||||||
#include "console.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) :
|
IdObject::IdObject(const std::weak_ptr<World>& world, std::string_view _id) :
|
||||||
Object{},
|
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,
|
id{this, "id", std::string(_id.data(), _id.size()), PropertyFlags::ReadWrite | PropertyFlags::Store, nullptr,
|
||||||
[this](std::string& value)
|
[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())
|
if(m.find(value) != m.end())
|
||||||
return false;
|
return false;
|
||||||
auto n = m.extract(id);
|
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();
|
auto w = world.lock();
|
||||||
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(id)
|
Attributes::addEnabled(id, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
IdObject::~IdObject()
|
IdObject::~IdObject()
|
||||||
|
|||||||
@ -27,12 +27,15 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "attribute.hpp"
|
#include "attribute.hpp"
|
||||||
|
#include "arrayattribute.hpp"
|
||||||
#include <traintastic/enum/category.hpp>
|
#include <traintastic/enum/category.hpp>
|
||||||
|
|
||||||
class Object;
|
class Object;
|
||||||
|
|
||||||
class InterfaceItem
|
class InterfaceItem
|
||||||
{
|
{
|
||||||
|
friend struct Attributes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Attributes = std::unordered_map<AttributeName, std::unique_ptr<AbstractAttribute>>;
|
using Attributes = std::unordered_map<AttributeName, std::unique_ptr<AbstractAttribute>>;
|
||||||
|
|
||||||
@ -42,10 +45,15 @@ class InterfaceItem
|
|||||||
Attributes m_attributes;
|
Attributes m_attributes;
|
||||||
|
|
||||||
template<typename T>
|
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));
|
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>
|
template<typename T>
|
||||||
@ -80,15 +88,6 @@ class InterfaceItem
|
|||||||
return m_attributes;
|
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); }
|
inline void setAttributeEnabled(bool value) { setAttribute(AttributeName::Enabled, value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -24,22 +24,39 @@
|
|||||||
#include "interfaceitem.hpp"
|
#include "interfaceitem.hpp"
|
||||||
#include <algorithm>
|
#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
|
InterfaceItem* InterfaceItems::find(const std::string& name) const
|
||||||
{
|
{
|
||||||
auto it = m_items.find(name);
|
auto it = m_items.find(name);
|
||||||
return (it != m_items.end()) ? &it->second : nullptr;
|
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_items.emplace(item.name(), item);
|
||||||
m_itemOrder.push_back(item.name());
|
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_items.emplace(item.name(), item);
|
||||||
m_itemOrder.insert(std::find(m_itemOrder.begin(), m_itemOrder.end(), before.name()), item.name());
|
m_itemOrder.insert(std::find(m_itemOrder.begin(), m_itemOrder.end(), before.name()), item.name());
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,8 +45,8 @@ class InterfaceItems
|
|||||||
|
|
||||||
InterfaceItem* find(const std::string& name) const;
|
InterfaceItem* find(const std::string& name) const;
|
||||||
|
|
||||||
InterfaceItem& add(InterfaceItem& item);
|
void add(InterfaceItem& item);
|
||||||
InterfaceItem& insertBefore(InterfaceItem& item, const InterfaceItem& before);
|
void insertBefore(InterfaceItem& item, const InterfaceItem& before);
|
||||||
|
|
||||||
inline InterfaceItem& operator[](const std::string& name) const { return m_items.at(name); }
|
inline InterfaceItem& operator[](const std::string& name) const { return m_items.at(name); }
|
||||||
};
|
};
|
||||||
|
|||||||
@ -26,8 +26,10 @@
|
|||||||
#include "traintastic.hpp"
|
#include "traintastic.hpp"
|
||||||
#include "client.hpp"
|
#include "client.hpp"
|
||||||
#include "abstractproperty.hpp"
|
#include "abstractproperty.hpp"
|
||||||
#include "abstractattribute.hpp"
|
#include "abstractvalueattribute.hpp"
|
||||||
|
#include "abstractvaluesattribute.hpp"
|
||||||
#include <traintastic/enum/interfaceitemtype.hpp>
|
#include <traintastic/enum/interfaceitemtype.hpp>
|
||||||
|
#include <traintastic/enum/attributetype.hpp>
|
||||||
#include "tablemodel.hpp"
|
#include "tablemodel.hpp"
|
||||||
#include "../world/world.hpp"
|
#include "../world/world.hpp"
|
||||||
#include "idobject.hpp"
|
#include "idobject.hpp"
|
||||||
@ -434,31 +436,7 @@ void Session::writeObject(Message& message, const ObjectPtr& object)
|
|||||||
{
|
{
|
||||||
const AbstractAttribute& attribute = *it.second;
|
const AbstractAttribute& attribute = *it.second;
|
||||||
message.writeBlock(); // attribute
|
message.writeBlock(); // attribute
|
||||||
message.write(attribute.name());
|
writeAttribute(message, attribute);
|
||||||
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;
|
|
||||||
}
|
|
||||||
message.writeBlockEnd(); // end attribute
|
message.writeBlockEnd(); // end attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,6 +525,8 @@ void Session::objectAttributeChanged(AbstractAttribute& attribute)
|
|||||||
auto event = Message::newEvent(Message::Command::ObjectAttributeChanged);
|
auto event = Message::newEvent(Message::Command::ObjectAttributeChanged);
|
||||||
event->write(m_handles.getHandle(attribute.item().object().shared_from_this()));
|
event->write(m_handles.getHandle(attribute.item().object().shared_from_this()));
|
||||||
event->write(attribute.item().name());
|
event->write(attribute.item().name());
|
||||||
|
writeAttribute(*event, attribute);
|
||||||
|
/*
|
||||||
event->write(attribute.name());
|
event->write(attribute.name());
|
||||||
event->write(attribute.type());
|
event->write(attribute.type());
|
||||||
switch(attribute.type())
|
switch(attribute.type())
|
||||||
@ -568,5 +548,74 @@ void Session::objectAttributeChanged(AbstractAttribute& attribute)
|
|||||||
//event->write(attribute.toString());
|
//event->write(attribute.toString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
m_client->sendMessage(std::move(event));
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@ -39,6 +39,9 @@ class Session : public std::enable_shared_from_this<Session>
|
|||||||
{
|
{
|
||||||
friend class Client;
|
friend class Client;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void writeAttribute(Message& message , const AbstractAttribute& attribute);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using Handle = uint32_t;
|
using Handle = uint32_t;
|
||||||
using Handles = HandleList<Handle, ObjectPtr>;
|
using Handles = HandleList<Handle, ObjectPtr>;
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <nlohmann/json.hpp>
|
#include "../utils/json.hpp"
|
||||||
|
|
||||||
class not_writable_error : public std::runtime_error
|
class not_writable_error : public std::runtime_error
|
||||||
{
|
{
|
||||||
@ -101,11 +101,16 @@ To to(const From& value)
|
|||||||
}
|
}
|
||||||
else if constexpr(std::is_same_v<From, nlohmann::json>)
|
else if constexpr(std::is_same_v<From, nlohmann::json>)
|
||||||
{
|
{
|
||||||
// if constexpr(std::is_same_v<To, bool>)
|
if constexpr(std::is_enum_v<To>)
|
||||||
return value;//.get<To>();
|
{
|
||||||
|
To e;
|
||||||
|
from_json(value, e);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
throw conversion_error();
|
throw conversion_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -165,7 +165,7 @@ class UnitProperty : public AbstractProperty//InterfaceItem
|
|||||||
void load(const nlohmann::json& value) final
|
void load(const nlohmann::json& value) final
|
||||||
{
|
{
|
||||||
m_value = to<T>(value["value"]);
|
m_value = to<T>(value["value"]);
|
||||||
m_unit = value["unit"];
|
from_json(value["unit"], m_unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(const ObjectPtr& value) final
|
void load(const ObjectPtr& value) final
|
||||||
|
|||||||
@ -31,16 +31,12 @@ template<typename T>
|
|||||||
class VectorAttribute : public AbstractAttribute
|
class VectorAttribute : public AbstractAttribute
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::vector<T> m_value;
|
std::vector<T> m_values;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
VectorAttribute(InterfaceItem& item, AttributeName name, const T& values) :
|
||||||
|
|
||||||
//dsjfnkjdnvjkdnkvjf
|
|
||||||
|
|
||||||
Attribute(InterfaceItem& item, AttributeName name, const T& value) :
|
|
||||||
AbstractAttribute{item, name, value_type_v<T>},
|
AbstractAttribute{item, name, value_type_v<T>},
|
||||||
m_value{value}
|
m_value{values}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,14 +29,6 @@
|
|||||||
#include "../lua/enumvalues.hpp"
|
#include "../lua/enumvalues.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(CommandStationStatus,
|
|
||||||
{
|
|
||||||
{CommandStationStatus::Offline, "offline"},
|
|
||||||
{CommandStationStatus::Initializing, "initializing"},
|
|
||||||
{CommandStationStatus::Online, "online"},
|
|
||||||
{CommandStationStatus::Error, "error"},
|
|
||||||
})
|
|
||||||
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
LUA_ENUM_VALUES(CommandStationStatus, 4,
|
LUA_ENUM_VALUES(CommandStationStatus, 4,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -29,12 +29,11 @@
|
|||||||
#include "../lua/enumvalues.hpp"
|
#include "../lua/enumvalues.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(DecoderProtocol,
|
inline constexpr std::array<DecoderProtocol, 3> DecoderProtocolValues{{
|
||||||
{
|
DecoderProtocol::Auto,
|
||||||
{DecoderProtocol::Auto, "AUTO"},
|
DecoderProtocol::DCC,
|
||||||
{DecoderProtocol::DCC, "DCC"},
|
DecoderProtocol::Custom,
|
||||||
{DecoderProtocol::Custom, "CUSTOM"},
|
}};
|
||||||
})
|
|
||||||
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
LUA_ENUM_VALUES(DecoderProtocol, 3,
|
LUA_ENUM_VALUES(DecoderProtocol, 3,
|
||||||
|
|||||||
@ -29,11 +29,11 @@
|
|||||||
#include "../lua/enumvalues.hpp"
|
#include "../lua/enumvalues.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(Direction,
|
inline constexpr std::array<Direction, 2> DirectionValues{{
|
||||||
{
|
Direction::Forward,
|
||||||
{Direction::Forward, "forward"},
|
Direction::Reverse,
|
||||||
{Direction::Reverse, "reverse"},
|
}};
|
||||||
})
|
|
||||||
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
LUA_ENUM_VALUES(Direction, 2,
|
LUA_ENUM_VALUES(Direction, 2,
|
||||||
|
|||||||
@ -24,16 +24,6 @@
|
|||||||
#define TRAINTASTIC_SERVER_ENUM_LENGTHUNIT_HPP
|
#define TRAINTASTIC_SERVER_ENUM_LENGTHUNIT_HPP
|
||||||
|
|
||||||
#include <traintastic/enum/lengthunit.hpp>
|
#include <traintastic/enum/lengthunit.hpp>
|
||||||
#include <nlohmann/json.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"},
|
|
||||||
})
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -31,23 +31,16 @@
|
|||||||
|
|
||||||
inline constexpr std::array<LocoNetCommandStation, 3> LocoNetCommandStationValues{{
|
inline constexpr std::array<LocoNetCommandStation, 3> LocoNetCommandStationValues{{
|
||||||
LocoNetCommandStation::Custom,
|
LocoNetCommandStation::Custom,
|
||||||
LocoNetCommandStation::DigiKeijsDR5000,
|
LocoNetCommandStation::DigikeijsDR5000,
|
||||||
LocoNetCommandStation::UhlenbrockIntellibox,
|
LocoNetCommandStation::UhlenbrockIntellibox,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(LocoNetCommandStation,
|
|
||||||
{
|
|
||||||
{LocoNetCommandStation::Custom, "custom"},
|
|
||||||
{LocoNetCommandStation::UhlenbrockIntellibox, "uhlenbrock_intellibox"},
|
|
||||||
{LocoNetCommandStation::DigiKeijsDR5000, "digikeijs_dr5000"},
|
|
||||||
})
|
|
||||||
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
LUA_ENUM_VALUES(LocoNetCommandStation, 3,
|
LUA_ENUM_VALUES(LocoNetCommandStation, 3,
|
||||||
{
|
{
|
||||||
{LocoNetCommandStation::Custom, "CUSTOM"},
|
{LocoNetCommandStation::Custom, "CUSTOM"},
|
||||||
{LocoNetCommandStation::UhlenbrockIntellibox, "UHLENBROCK_INTELLIBOX"},
|
{LocoNetCommandStation::UhlenbrockIntellibox, "UHLENBROCK_INTELLIBOX"},
|
||||||
{LocoNetCommandStation::DigiKeijsDR5000, "DIGIKEIJS_DR5000"},
|
{LocoNetCommandStation::DigikeijsDR5000, "DIGIKEIJS_DR5000"},
|
||||||
})
|
})
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -31,22 +31,15 @@
|
|||||||
|
|
||||||
inline constexpr std::array<LocoNetSerialInterface, 3> LocoNetSerialInterfaceValues{{
|
inline constexpr std::array<LocoNetSerialInterface, 3> LocoNetSerialInterfaceValues{{
|
||||||
LocoNetSerialInterface::Custom,
|
LocoNetSerialInterface::Custom,
|
||||||
LocoNetSerialInterface::DigiKeijsDR5000,
|
LocoNetSerialInterface::DigikeijsDR5000,
|
||||||
LocoNetSerialInterface::RoSoftLocoNetInterface,
|
LocoNetSerialInterface::RoSoftLocoNetInterface,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(LocoNetSerialInterface,
|
|
||||||
{
|
|
||||||
{LocoNetSerialInterface::Custom, "custom"},
|
|
||||||
{LocoNetSerialInterface::DigiKeijsDR5000, "digikeijs_dr5000"},
|
|
||||||
{LocoNetSerialInterface::RoSoftLocoNetInterface, "rosoft_loconet_interface"},
|
|
||||||
})
|
|
||||||
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
LUA_ENUM_VALUES(LocoNetSerialInterface, 3,
|
LUA_ENUM_VALUES(LocoNetSerialInterface, 3,
|
||||||
{
|
{
|
||||||
{LocoNetSerialInterface::Custom, "CUSTOM"},
|
{LocoNetSerialInterface::Custom, "CUSTOM"},
|
||||||
{LocoNetSerialInterface::DigiKeijsDR5000, "DIGIKEIJS_DR5000"},
|
{LocoNetSerialInterface::DigikeijsDR5000, "DIGIKEIJS_DR5000"},
|
||||||
{LocoNetSerialInterface::RoSoftLocoNetInterface, "ROSOFT_LOCONET_INTERFACE"},
|
{LocoNetSerialInterface::RoSoftLocoNetInterface, "ROSOFT_LOCONET_INTERFACE"},
|
||||||
})
|
})
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -34,12 +34,6 @@ inline constexpr std::array<SerialFlowControl, 2> SerialFlowControlValues{{
|
|||||||
SerialFlowControl::Hardware,
|
SerialFlowControl::Hardware,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(SerialFlowControl,
|
|
||||||
{
|
|
||||||
{SerialFlowControl::None, "none"},
|
|
||||||
{SerialFlowControl::Hardware, "hardware"},
|
|
||||||
})
|
|
||||||
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
LUA_ENUM_VALUES(SerialFlowControl, 2,
|
LUA_ENUM_VALUES(SerialFlowControl, 2,
|
||||||
{
|
{
|
||||||
|
|||||||
36
server/src/enum/worldscale.hpp
Normale Datei
36
server/src/enum/worldscale.hpp
Normale Datei
@ -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
|
||||||
@ -24,18 +24,15 @@
|
|||||||
#define TRAINTASTIC_SERVER_ENUM_XPRESSNETCOMMANDSTATION_HPP
|
#define TRAINTASTIC_SERVER_ENUM_XPRESSNETCOMMANDSTATION_HPP
|
||||||
|
|
||||||
#include <traintastic/enum/xpressnetcommandstation.hpp>
|
#include <traintastic/enum/xpressnetcommandstation.hpp>
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
#include "../lua/enumvalues.hpp"
|
#include "../lua/enumvalues.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline constexpr std::array<XpressNetCommandStation, 2> XpressNetCommandStationValues{{XpressNetCommandStation::Custom, XpressNetCommandStation::Roco10764}};
|
inline constexpr std::array<XpressNetCommandStation, 3> XpressNetCommandStationValues{{
|
||||||
|
XpressNetCommandStation::Custom,
|
||||||
NLOHMANN_JSON_SERIALIZE_ENUM(XpressNetCommandStation,
|
XpressNetCommandStation::Roco10764,
|
||||||
{
|
XpressNetCommandStation::DigikeijsDR5000,
|
||||||
{XpressNetCommandStation::Custom, "custom"},
|
}};
|
||||||
{XpressNetCommandStation::Roco10764, "roco_10764"},
|
|
||||||
})
|
|
||||||
|
|
||||||
#ifndef DISABLE_LUA_SCRIPTING
|
#ifndef DISABLE_LUA_SCRIPTING
|
||||||
LUA_ENUM_VALUES(XpressNetCommandStation, 2,
|
LUA_ENUM_VALUES(XpressNetCommandStation, 2,
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
#define TRAINTASTIC_SERVER_ENUM_XPRESSNETSERIALINTERFACE_HPP
|
#define TRAINTASTIC_SERVER_ENUM_XPRESSNETSERIALINTERFACE_HPP
|
||||||
|
|
||||||
#include <traintastic/enum/xpressnetserialinterface.hpp>
|
#include <traintastic/enum/xpressnetserialinterface.hpp>
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
inline constexpr std::array<XpressNetSerialInterface, 5> XpressNetSerialInterfaceValues{{
|
inline constexpr std::array<XpressNetSerialInterface, 5> XpressNetSerialInterfaceValues{{
|
||||||
XpressNetSerialInterface::Custom,
|
XpressNetSerialInterface::Custom,
|
||||||
@ -34,13 +33,4 @@ inline constexpr std::array<XpressNetSerialInterface, 5> XpressNetSerialInterfac
|
|||||||
XpressNetSerialInterface::RoSoftS88XPressNetLI,
|
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
|
#endif
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include "../../world/world.hpp"
|
#include "../../world/world.hpp"
|
||||||
#include "../decoder/decoder.hpp"
|
#include "../decoder/decoder.hpp"
|
||||||
#include "../decoder/decoderlist.hpp"
|
#include "../decoder/decoderlist.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
CommandStation::CommandStation(const std::weak_ptr<World>& world, std::string_view _id) :
|
CommandStation::CommandStation(const std::weak_ptr<World>& world, std::string_view _id) :
|
||||||
IdObject(world, _id),
|
IdObject(world, _id),
|
||||||
@ -59,17 +60,21 @@ CommandStation::CommandStation(const std::weak_ptr<World>& world, std::string_vi
|
|||||||
auto w = world.lock();
|
auto w = world.lock();
|
||||||
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(name)
|
Attributes::addEnabled(name, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(name);
|
||||||
|
|
||||||
m_interfaceItems.add(online);
|
m_interfaceItems.add(online);
|
||||||
m_interfaceItems.insertBefore(emergencyStop, notes)
|
|
||||||
.addAttributeEnabled(editable)
|
Attributes::addObjectEditor(emergencyStop, false);
|
||||||
.addAttributeObjectEditor(false);
|
m_interfaceItems.insertBefore(emergencyStop, notes);
|
||||||
m_interfaceItems.insertBefore(trackVoltageOff, notes)
|
|
||||||
.addAttributeEnabled(editable)
|
Attributes::addObjectEditor(trackVoltageOff, false);
|
||||||
.addAttributeObjectEditor(false);
|
m_interfaceItems.insertBefore(trackVoltageOff, notes);
|
||||||
|
|
||||||
m_interfaceItems.add(decoders);
|
m_interfaceItems.add(decoders);
|
||||||
|
|
||||||
m_interfaceItems.add(controllers);
|
m_interfaceItems.add(controllers);
|
||||||
|
|
||||||
m_interfaceItems.add(notes);
|
m_interfaceItems.add(notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "commandstations.hpp"
|
#include "commandstations.hpp"
|
||||||
#include "../../world/world.hpp"
|
#include "../../world/world.hpp"
|
||||||
#include "../../world/getworld.hpp"
|
#include "../../world/getworld.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
CommandStationList::CommandStationList(Object& _parent, const std::string& parentPropertyName) :
|
CommandStationList::CommandStationList(Object& _parent, const std::string& parentPropertyName) :
|
||||||
ObjectList<CommandStation>(_parent, parentPropertyName),
|
ObjectList<CommandStation>(_parent, parentPropertyName),
|
||||||
@ -47,11 +48,12 @@ CommandStationList::CommandStationList(Object& _parent, const std::string& paren
|
|||||||
auto world = getWorld(&_parent);
|
auto world = getWorld(&_parent);
|
||||||
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(add)
|
Attributes::addEnabled(add, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(add);
|
||||||
m_interfaceItems.add(remove)
|
|
||||||
.addAttributeEnabled(editable);
|
Attributes::addEnabled(remove, editable);
|
||||||
}
|
m_interfaceItems.add(remove);
|
||||||
|
}
|
||||||
|
|
||||||
TableModelPtr CommandStationList::getModel()
|
TableModelPtr CommandStationList::getModel()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_CREATE_HPP
|
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_COMMANDSTATIONS_HPP
|
||||||
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_CREATE_HPP
|
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_COMMANDSTATIONS_HPP
|
||||||
|
|
||||||
#include "commandstation.hpp"
|
#include "commandstation.hpp"
|
||||||
|
|
||||||
|
|||||||
@ -21,9 +21,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "loconetserial.hpp"
|
#include "loconetserial.hpp"
|
||||||
//#include "../../world/world.hpp"
|
|
||||||
#include "../../core/traintastic.hpp"
|
#include "../../core/traintastic.hpp"
|
||||||
#include "../../core/eventloop.hpp"
|
#include "../../core/eventloop.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
LocoNetSerial::LocoNetSerial(const std::weak_ptr<World>& world, std::string_view _id) :
|
LocoNetSerial::LocoNetSerial(const std::weak_ptr<World>& world, std::string_view _id) :
|
||||||
SerialCommandStation(world, _id),
|
SerialCommandStation(world, _id),
|
||||||
@ -35,7 +35,7 @@ LocoNetSerial::LocoNetSerial(const std::weak_ptr<World>& world, std::string_view
|
|||||||
case LocoNetSerialInterface::Custom:
|
case LocoNetSerialInterface::Custom:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LocoNetSerialInterface::DigiKeijsDR5000:
|
case LocoNetSerialInterface::DigikeijsDR5000:
|
||||||
baudrate = 115200;
|
baudrate = 115200;
|
||||||
flowControl = SerialFlowControl::Hardware;
|
flowControl = SerialFlowControl::Hardware;
|
||||||
break;
|
break;
|
||||||
@ -51,31 +51,11 @@ LocoNetSerial::LocoNetSerial(const std::weak_ptr<World>& world, std::string_view
|
|||||||
name = "LocoNet (serial)";
|
name = "LocoNet (serial)";
|
||||||
loconet.setValueInternal(std::make_shared<LocoNet::LocoNet>(*this, loconet.name(), std::bind(&LocoNetSerial::send, this, std::placeholders::_1)));
|
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(interface, baudrate);
|
||||||
m_interfaceItems.insertBefore(loconet, notes);
|
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)
|
void LocoNetSerial::emergencyStopChanged(bool value)
|
||||||
{
|
{
|
||||||
@ -115,6 +95,11 @@ bool LocoNetSerial::send(const LocoNet::Message& message)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocoNetSerial::started()
|
||||||
|
{
|
||||||
|
loconet->queryLocoSlots();
|
||||||
|
}
|
||||||
|
|
||||||
void LocoNetSerial::read()
|
void LocoNetSerial::read()
|
||||||
{
|
{
|
||||||
m_serialPort.async_read_some(boost::asio::buffer(m_readBuffer.data() + m_readBufferOffset, m_readBuffer.size() - m_readBufferOffset),
|
m_serialPort.async_read_some(boost::asio::buffer(m_readBuffer.data() + m_readBufferOffset, m_readBuffer.size() - m_readBufferOffset),
|
||||||
|
|||||||
@ -26,8 +26,6 @@
|
|||||||
#include "serialcommandstation.hpp"
|
#include "serialcommandstation.hpp"
|
||||||
#include "../protocol/loconet/loconet.hpp"
|
#include "../protocol/loconet/loconet.hpp"
|
||||||
#include "../../enum/loconetserialinterface.hpp"
|
#include "../../enum/loconetserialinterface.hpp"
|
||||||
//#include "../../enum/serialflowcontrol.hpp"
|
|
||||||
//#include <boost/asio/serial_port.hpp>
|
|
||||||
|
|
||||||
class LocoNetSerial : public SerialCommandStation
|
class LocoNetSerial : public SerialCommandStation
|
||||||
{
|
{
|
||||||
@ -39,6 +37,7 @@ class LocoNetSerial : public SerialCommandStation
|
|||||||
bool start();
|
bool start();
|
||||||
void stop();
|
void stop();
|
||||||
bool send(const LocoNet::Message& msg);
|
bool send(const LocoNet::Message& msg);
|
||||||
|
void started() final;
|
||||||
void read() final;
|
void read() final;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -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
|
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include "../../core/traintastic.hpp"
|
#include "../../core/traintastic.hpp"
|
||||||
#include "../../world/world.hpp"
|
#include "../../world/world.hpp"
|
||||||
#include "../../core/eventloop.hpp"
|
#include "../../core/eventloop.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
#include "../decoder/decoderchangeflags.hpp"
|
#include "../decoder/decoderchangeflags.hpp"
|
||||||
#include "../protocol/xpressnet/messages.hpp"
|
#include "../protocol/xpressnet/messages.hpp"
|
||||||
#include "../protocol/z21.hpp"
|
#include "../protocol/z21.hpp"
|
||||||
@ -87,41 +88,41 @@ RocoZ21::RocoZ21(const std::weak_ptr<World>& world, std::string_view _id) :
|
|||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
m_interfaceItems.insertBefore(hostname, notes)
|
Attributes::addEnabled(hostname, true);
|
||||||
.addAttributeEnabled(true);
|
m_interfaceItems.insertBefore(hostname, notes);
|
||||||
m_interfaceItems.insertBefore(port, notes)
|
Attributes::addEnabled(port, true);
|
||||||
.addAttributeEnabled(true);
|
m_interfaceItems.insertBefore(port, notes);
|
||||||
m_interfaceItems.insertBefore(loconet, notes);
|
m_interfaceItems.insertBefore(loconet, notes);
|
||||||
m_interfaceItems.insertBefore(serialNumber, notes)
|
Attributes::addCategory(serialNumber, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(serialNumber, notes);
|
||||||
m_interfaceItems.insertBefore(hardwareType, notes)
|
Attributes::addCategory(hardwareType, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(hardwareType, notes);
|
||||||
m_interfaceItems.insertBefore(firmwareVersion, notes)
|
Attributes::addCategory(firmwareVersion, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(firmwareVersion, notes);
|
||||||
m_interfaceItems.insertBefore(mainCurrent, notes)
|
Attributes::addCategory(mainCurrent, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(mainCurrent, notes);
|
||||||
m_interfaceItems.insertBefore(progCurrent, notes)
|
Attributes::addCategory(progCurrent, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(progCurrent, notes);
|
||||||
m_interfaceItems.insertBefore(filteredMainCurrent, notes)
|
Attributes::addCategory(filteredMainCurrent, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(filteredMainCurrent, notes);
|
||||||
m_interfaceItems.insertBefore(temperature, notes)
|
Attributes::addCategory(temperature, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(temperature, notes);
|
||||||
m_interfaceItems.insertBefore(supplyVoltage, notes)
|
Attributes::addCategory(firmwareVersion, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(supplyVoltage, notes);
|
||||||
m_interfaceItems.insertBefore(vccVoltage, notes)
|
Attributes::addCategory(vccVoltage, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(vccVoltage, notes);
|
||||||
m_interfaceItems.insertBefore(shortCircuit, notes)
|
Attributes::addCategory(firmwareVersion, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(shortCircuit, notes);
|
||||||
m_interfaceItems.insertBefore(programmingModeActive, notes)
|
Attributes::addCategory(programmingModeActive, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(programmingModeActive, notes);
|
||||||
m_interfaceItems.insertBefore(highTemperature, notes)
|
Attributes::addCategory(highTemperature, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(highTemperature, notes);
|
||||||
m_interfaceItems.insertBefore(powerLost, notes)
|
Attributes::addCategory(powerLost, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(powerLost, notes);
|
||||||
m_interfaceItems.insertBefore(shortCircutInternal, notes)
|
Attributes::addCategory(shortCircutInternal, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(shortCircutInternal, notes);
|
||||||
m_interfaceItems.insertBefore(shortCircutExternal, notes)
|
Attributes::addCategory(shortCircutExternal, Category::Info);
|
||||||
.addAttributeCategory(Category::Info);
|
m_interfaceItems.insertBefore(shortCircutExternal, notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RocoZ21::emergencyStopChanged(bool value)
|
void RocoZ21::emergencyStopChanged(bool value)
|
||||||
|
|||||||
@ -20,8 +20,8 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_Z21_HPP
|
#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_ROCOZ21_HPP
|
||||||
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_Z21_HPP
|
#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_ROCOZ21_HPP
|
||||||
|
|
||||||
#include "commandstation.hpp"
|
#include "commandstation.hpp"
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "serialcommandstation.hpp"
|
#include "serialcommandstation.hpp"
|
||||||
#include "../../core/traintastic.hpp"
|
#include "../../core/traintastic.hpp"
|
||||||
#include "../../core/eventloop.hpp"
|
#include "../../core/eventloop.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
SerialCommandStation::SerialCommandStation(const std::weak_ptr<World>& world, std::string_view _id) :
|
SerialCommandStation::SerialCommandStation(const std::weak_ptr<World>& world, std::string_view _id) :
|
||||||
CommandStation(world, _id),
|
CommandStation(world, _id),
|
||||||
@ -40,12 +41,12 @@ SerialCommandStation::SerialCommandStation(const std::weak_ptr<World>& world, st
|
|||||||
//interface = LocoNetSerialInterface::Custom;
|
//interface = LocoNetSerialInterface::Custom;
|
||||||
}}
|
}}
|
||||||
{
|
{
|
||||||
port.addAttributeEnabled(!online);
|
Attributes::addEnabled(port, !online);
|
||||||
baudrate.addAttributeEnabled(!online);
|
|
||||||
flowControl.addAttributeEnabled(!online);
|
|
||||||
|
|
||||||
m_interfaceItems.insertBefore(port, notes);
|
m_interfaceItems.insertBefore(port, notes);
|
||||||
|
Attributes::addEnabled(baudrate, !online);
|
||||||
m_interfaceItems.insertBefore(baudrate, notes);
|
m_interfaceItems.insertBefore(baudrate, notes);
|
||||||
|
Attributes::addEnabled(flowControl, !online);
|
||||||
|
Attributes::addValues(flowControl, SerialFlowControlValues);
|
||||||
m_interfaceItems.insertBefore(flowControl, notes);
|
m_interfaceItems.insertBefore(flowControl, notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +61,6 @@ bool SerialCommandStation::setOnline(bool& value)
|
|||||||
}
|
}
|
||||||
m_readBufferOffset = 0;
|
m_readBufferOffset = 0;
|
||||||
read();
|
read();
|
||||||
|
|
||||||
//loconet->queryLocoSlots();
|
|
||||||
}
|
}
|
||||||
else if(m_serialPort.is_open() && !value)
|
else if(m_serialPort.is_open() && !value)
|
||||||
stop();
|
stop();
|
||||||
|
|||||||
@ -38,6 +38,8 @@ class SerialCommandStation : public CommandStation
|
|||||||
|
|
||||||
bool start();
|
bool start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
virtual void started() {}
|
||||||
virtual void read() = 0;
|
virtual void read() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -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
|
|
||||||
@ -24,6 +24,7 @@
|
|||||||
#include "../../world/world.hpp"
|
#include "../../world/world.hpp"
|
||||||
#include "../../core/traintastic.hpp"
|
#include "../../core/traintastic.hpp"
|
||||||
#include "../../core/eventloop.hpp"
|
#include "../../core/eventloop.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
XpressNetSerial::XpressNetSerial(const std::weak_ptr<World>& world, std::string_view _id) :
|
XpressNetSerial::XpressNetSerial(const std::weak_ptr<World>& world, std::string_view _id) :
|
||||||
SerialCommandStation(world, _id),
|
SerialCommandStation(world, _id),
|
||||||
@ -57,6 +58,7 @@ XpressNetSerial::XpressNetSerial(const std::weak_ptr<World>& world, std::string_
|
|||||||
name = "XpressNet (serial)";
|
name = "XpressNet (serial)";
|
||||||
xpressnet.setValueInternal(std::make_shared<XpressNet::XpressNet>(*this, xpressnet.name(), std::bind(&XpressNetSerial::send, this, std::placeholders::_1)));
|
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(interface, baudrate);
|
||||||
m_interfaceItems.insertBefore(xpressnet, notes);
|
m_interfaceItems.insertBefore(xpressnet, notes);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "controllerlisttablemodel.hpp"
|
#include "controllerlisttablemodel.hpp"
|
||||||
#include "../commandstation/commandstation.hpp"
|
#include "../commandstation/commandstation.hpp"
|
||||||
#include "../../world/getworld.hpp"
|
#include "../../world/getworld.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
Controller::Controller(const std::weak_ptr<World>& _world, std::string_view _id) :
|
Controller::Controller(const std::weak_ptr<World>& _world, std::string_view _id) :
|
||||||
IdObject(_world, _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);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(name);
|
m_interfaceItems.add(name);
|
||||||
m_interfaceItems.add(commandStation)
|
Attributes::addEnabled(commandStation, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(commandStation);
|
||||||
m_interfaceItems.add(active);
|
m_interfaceItems.add(active);
|
||||||
m_interfaceItems.add(notes);
|
m_interfaceItems.add(notes);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "controllers.hpp"
|
#include "controllers.hpp"
|
||||||
#include "../commandstation/commandstation.hpp"
|
#include "../commandstation/commandstation.hpp"
|
||||||
#include "../../world/getworld.hpp"
|
#include "../../world/getworld.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
ControllerList::ControllerList(Object& _parent, const std::string& parentPropertyName) :
|
ControllerList::ControllerList(Object& _parent, const std::string& parentPropertyName) :
|
||||||
ObjectList<Controller>(_parent, parentPropertyName),
|
ObjectList<Controller>(_parent, parentPropertyName),
|
||||||
@ -45,8 +46,8 @@ ControllerList::ControllerList(Object& _parent, const std::string& parentPropert
|
|||||||
auto world = getWorld(&_parent);
|
auto world = getWorld(&_parent);
|
||||||
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(add)
|
Attributes::addEnabled(add, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableModelPtr ControllerList::getModel()
|
TableModelPtr ControllerList::getModel()
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include "../decoder/decoder.hpp"
|
#include "../decoder/decoder.hpp"
|
||||||
#include "../protocol/z21.hpp"
|
#include "../protocol/z21.hpp"
|
||||||
#include "../../utils/to_hex.hpp"
|
#include "../../utils/to_hex.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
WLANmaus::WLANmaus(const std::weak_ptr<World> world, std::string_view _id) :
|
WLANmaus::WLANmaus(const std::weak_ptr<World> world, std::string_view _id) :
|
||||||
Controller(world, _id),
|
Controller(world, _id),
|
||||||
@ -34,8 +35,8 @@ WLANmaus::WLANmaus(const std::weak_ptr<World> world, std::string_view _id) :
|
|||||||
m_blockLocoInfo{nullptr},
|
m_blockLocoInfo{nullptr},
|
||||||
port{this, "port", 21105, PropertyFlags::ReadWrite | PropertyFlags::Store}
|
port{this, "port", 21105, PropertyFlags::ReadWrite | PropertyFlags::Store}
|
||||||
{
|
{
|
||||||
m_interfaceItems.add(port)
|
Attributes::addEnabled(port, !active);
|
||||||
.addAttributeEnabled(!active);
|
m_interfaceItems.add(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WLANmaus::setActive(bool& value)
|
bool WLANmaus::setActive(bool& value)
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "decoderfunctionlist.hpp"
|
#include "decoderfunctionlist.hpp"
|
||||||
#include "../../world/world.hpp"
|
#include "../../world/world.hpp"
|
||||||
#include "../commandstation/commandstation.hpp"
|
#include "../commandstation/commandstation.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
//constexpr uint16_t addressDCCMin = 1;
|
//constexpr uint16_t addressDCCMin = 1;
|
||||||
constexpr uint16_t addressDCCShortMax = 127;
|
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();
|
//auto w = world.lock();
|
||||||
// const bool editable = w && contains(w->state.value(), WorldState::Edit) && speedStep == 0;
|
// const bool editable = w && contains(w->state.value(), WorldState::Edit) && speedStep == 0;
|
||||||
|
|
||||||
m_interfaceItems.add(name)
|
Attributes::addEnabled(name, false);
|
||||||
.addAttributeEnabled(false);
|
m_interfaceItems.add(name);
|
||||||
m_interfaceItems.add(commandStation)
|
Attributes::addEnabled(commandStation, false);
|
||||||
.addAttributeEnabled(false);
|
m_interfaceItems.add(commandStation);
|
||||||
m_interfaceItems.add(protocol)
|
Attributes::addEnabled(protocol, false);
|
||||||
.addAttributeEnabled(false);
|
Attributes::addValues(protocol, DecoderProtocolValues);
|
||||||
m_interfaceItems.add(address)
|
m_interfaceItems.add(protocol);
|
||||||
.addAttributeEnabled(false);
|
Attributes::addEnabled(address, false);
|
||||||
m_interfaceItems.add(longAddress)
|
m_interfaceItems.add(address);
|
||||||
.addAttributeEnabled(false);
|
Attributes::addEnabled(longAddress, false);
|
||||||
|
m_interfaceItems.add(longAddress);
|
||||||
m_interfaceItems.add(emergencyStop);
|
m_interfaceItems.add(emergencyStop);
|
||||||
|
Attributes::addValues(direction, DirectionValues);
|
||||||
m_interfaceItems.add(direction);
|
m_interfaceItems.add(direction);
|
||||||
m_interfaceItems.add(speedSteps)
|
Attributes::addEnabled(speedSteps, false);
|
||||||
.addAttributeEnabled(false);
|
m_interfaceItems.add(speedSteps);
|
||||||
m_interfaceItems.add(speedStep);
|
m_interfaceItems.add(speedStep);
|
||||||
m_interfaceItems.add(functions);
|
m_interfaceItems.add(functions);
|
||||||
m_interfaceItems.add(notes);
|
m_interfaceItems.add(notes);
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#include "decoder.hpp"
|
#include "decoder.hpp"
|
||||||
#include "decoderchangeflags.hpp"
|
#include "decoderchangeflags.hpp"
|
||||||
#include "../../world/world.hpp"
|
#include "../../world/world.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
const std::shared_ptr<DecoderFunction> DecoderFunction::null;
|
const std::shared_ptr<DecoderFunction> DecoderFunction::null;
|
||||||
|
|
||||||
@ -41,10 +42,10 @@ DecoderFunction::DecoderFunction(Decoder& decoder, std::string_view _id) :
|
|||||||
auto w = decoder.world().lock();
|
auto w = decoder.world().lock();
|
||||||
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(number)
|
Attributes::addEnabled(number, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(number);
|
||||||
m_interfaceItems.add(name)
|
Attributes::addEnabled(name, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecoderFunction::worldEvent(WorldState state, WorldEvent event)
|
void DecoderFunction::worldEvent(WorldState state, WorldEvent event)
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "decoderfunctionlisttablemodel.hpp"
|
#include "decoderfunctionlisttablemodel.hpp"
|
||||||
#include "decoder.hpp"
|
#include "decoder.hpp"
|
||||||
#include "../../world/getworld.hpp"
|
#include "../../world/getworld.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
DecoderFunctionList::DecoderFunctionList(Object& _parent, const std::string& parentPropertyName) :
|
DecoderFunctionList::DecoderFunctionList(Object& _parent, const std::string& parentPropertyName) :
|
||||||
ObjectList<DecoderFunction>(_parent, parentPropertyName),
|
ObjectList<DecoderFunction>(_parent, parentPropertyName),
|
||||||
@ -57,8 +58,8 @@ DecoderFunctionList::DecoderFunctionList(Object& _parent, const std::string& par
|
|||||||
auto world = getWorld(&_parent);
|
auto world = getWorld(&_parent);
|
||||||
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(add)
|
Attributes::addEnabled(add, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableModelPtr DecoderFunctionList::getModel()
|
TableModelPtr DecoderFunctionList::getModel()
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "decoderlisttablemodel.hpp"
|
#include "decoderlisttablemodel.hpp"
|
||||||
#include "../commandstation/commandstation.hpp"
|
#include "../commandstation/commandstation.hpp"
|
||||||
#include "../../world/getworld.hpp"
|
#include "../../world/getworld.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
DecoderList::DecoderList(Object& _parent, const std::string& parentPropertyName) :
|
DecoderList::DecoderList(Object& _parent, const std::string& parentPropertyName) :
|
||||||
ObjectList<Decoder>(_parent, parentPropertyName),
|
ObjectList<Decoder>(_parent, parentPropertyName),
|
||||||
@ -45,8 +46,8 @@ DecoderList::DecoderList(Object& _parent, const std::string& parentPropertyName)
|
|||||||
auto world = getWorld(&_parent);
|
auto world = getWorld(&_parent);
|
||||||
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(add)
|
Attributes::addEnabled(add, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableModelPtr DecoderList::getModel()
|
TableModelPtr DecoderList::getModel()
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "loconetinput.hpp"
|
#include "loconetinput.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
LocoNetInput::LocoNetInput(const std::weak_ptr<World> world, std::string_view _id) :
|
LocoNetInput::LocoNetInput(const std::weak_ptr<World> world, std::string_view _id) :
|
||||||
Input(world, _id),
|
Input(world, _id),
|
||||||
@ -44,10 +45,10 @@ LocoNetInput::LocoNetInput(const std::weak_ptr<World> world, std::string_view _i
|
|||||||
return false;
|
return false;
|
||||||
}}
|
}}
|
||||||
{
|
{
|
||||||
m_interfaceItems.add(loconet)
|
Attributes::addEnabled(loconet, false);
|
||||||
.addAttributeEnabled(false);
|
m_interfaceItems.add(loconet);
|
||||||
m_interfaceItems.add(address)
|
Attributes::addEnabled(address, false);
|
||||||
.addAttributeEnabled(false);
|
m_interfaceItems.add(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocoNetInput::worldEvent(WorldState state, WorldEvent event)
|
void LocoNetInput::worldEvent(WorldState state, WorldEvent event)
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include "../../../core/traintastic.hpp"
|
#include "../../../core/traintastic.hpp"
|
||||||
#include "../../commandstation/commandstation.hpp"
|
#include "../../commandstation/commandstation.hpp"
|
||||||
#include "../../input/loconetinput.hpp"
|
#include "../../input/loconetinput.hpp"
|
||||||
|
#include "../../../core/attributes.hpp"
|
||||||
|
|
||||||
namespace LocoNet {
|
namespace LocoNet {
|
||||||
|
|
||||||
@ -44,9 +45,9 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu
|
|||||||
SubObject(_parent, parentPropertyName),
|
SubObject(_parent, parentPropertyName),
|
||||||
m_commandStation{dynamic_cast<CommandStation*>(&_parent)},
|
m_commandStation{dynamic_cast<CommandStation*>(&_parent)},
|
||||||
m_send{std::move(send)},
|
m_send{std::move(send)},
|
||||||
m_debugLog{true/*false*/},
|
m_debugLog{false},
|
||||||
m_queryLocoSlots{SLOT_UNKNOWN},
|
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)
|
[this](LocoNetCommandStation value)
|
||||||
{
|
{
|
||||||
switch(value)
|
switch(value)
|
||||||
@ -54,7 +55,7 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu
|
|||||||
case LocoNetCommandStation::Custom:
|
case LocoNetCommandStation::Custom:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LocoNetCommandStation::DigiKeijsDR5000:
|
case LocoNetCommandStation::DigikeijsDR5000:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LocoNetCommandStation::UhlenbrockIntellibox:
|
case LocoNetCommandStation::UhlenbrockIntellibox:
|
||||||
@ -69,8 +70,9 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu
|
|||||||
{
|
{
|
||||||
assert(m_send);
|
assert(m_send);
|
||||||
|
|
||||||
m_interfaceItems.add(commandStation)
|
Attributes::addEnabled(commandStation, m_commandStation && !m_commandStation->online);
|
||||||
.addAttributeEnabled(false);
|
Attributes::addValues(commandStation, LocoNetCommandStationValues);
|
||||||
|
m_interfaceItems.add(commandStation);
|
||||||
m_interfaceItems.add(debugLog);
|
m_interfaceItems.add(debugLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "../../../core/traintastic.hpp"
|
#include "../../../core/traintastic.hpp"
|
||||||
#include "../../../core/eventloop.hpp"
|
#include "../../../core/eventloop.hpp"
|
||||||
#include "../../decoder/decoder.hpp"
|
#include "../../decoder/decoder.hpp"
|
||||||
|
#include "../../../core/attributes.hpp"
|
||||||
|
|
||||||
namespace XpressNet {
|
namespace XpressNet {
|
||||||
|
|
||||||
@ -42,21 +43,28 @@ XpressNet::XpressNet(Object& _parent, const std::string& parentPropertyName, std
|
|||||||
|
|
||||||
case XpressNetCommandStation::Roco10764:
|
case XpressNetCommandStation::Roco10764:
|
||||||
useEmergencyStopLocomotiveCommand.setValueInternal(false);
|
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);
|
useRocoF13F20Command.setValueInternal(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// TODO: updateEnabled();
|
||||||
}},
|
}},
|
||||||
useEmergencyStopLocomotiveCommand{this, "use_emergency_stop_locomotive_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
useEmergencyStopLocomotiveCommand{this, "use_emergency_stop_locomotive_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
||||||
[this](bool)
|
[this](bool)
|
||||||
{
|
{
|
||||||
commandStation = XpressNetCommandStation::Custom;
|
commandStation = XpressNetCommandStation::Custom;
|
||||||
}},
|
}},
|
||||||
useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
//useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
||||||
[this](bool)
|
// [this](bool)
|
||||||
{
|
// {
|
||||||
commandStation = XpressNetCommandStation::Custom;
|
// commandStation = XpressNetCommandStation::Custom;
|
||||||
}},
|
// }},
|
||||||
useRocoF13F20Command{this, "use_roco_f13_f20_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
useRocoF13F20Command{this, "use_roco_f13_f20_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
||||||
[this](bool)
|
[this](bool)
|
||||||
{
|
{
|
||||||
@ -68,14 +76,15 @@ XpressNet::XpressNet(Object& _parent, const std::string& parentPropertyName, std
|
|||||||
m_debugLog = value;
|
m_debugLog = value;
|
||||||
}}
|
}}
|
||||||
{
|
{
|
||||||
m_interfaceItems.add(commandStation)
|
Attributes::addEnabled(commandStation, false);
|
||||||
.addAttributeEnabled(false);
|
Attributes::addValues(commandStation, XpressNetCommandStationValues);
|
||||||
m_interfaceItems.add(useEmergencyStopLocomotiveCommand)
|
m_interfaceItems.add(commandStation);
|
||||||
.addAttributeEnabled(false);
|
Attributes::addEnabled(useEmergencyStopLocomotiveCommand, false);
|
||||||
m_interfaceItems.add(useFunctionStateCommands)
|
m_interfaceItems.add(useEmergencyStopLocomotiveCommand);
|
||||||
.addAttributeEnabled(false);
|
//Attributes::addEnabled(useFunctionStateCommands, false);
|
||||||
m_interfaceItems.add(useRocoF13F20Command)
|
//m_interfaceItems.add(useFunctionStateCommands);
|
||||||
.addAttributeEnabled(false);
|
Attributes::addEnabled(useRocoF13F20Command, false);
|
||||||
|
m_interfaceItems.add(useRocoF13F20Command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void XpressNet::worldEvent(WorldState state, WorldEvent event)
|
void XpressNet::worldEvent(WorldState state, WorldEvent event)
|
||||||
@ -86,7 +95,7 @@ void XpressNet::worldEvent(WorldState state, WorldEvent event)
|
|||||||
|
|
||||||
commandStation.setAttributeEnabled(editable);
|
commandStation.setAttributeEnabled(editable);
|
||||||
useEmergencyStopLocomotiveCommand.setAttributeEnabled(editable);
|
useEmergencyStopLocomotiveCommand.setAttributeEnabled(editable);
|
||||||
useFunctionStateCommands.setAttributeEnabled(editable);
|
//useFunctionStateCommands.setAttributeEnabled(editable);
|
||||||
useRocoF13F20Command.setAttributeEnabled(editable);
|
useRocoF13F20Command.setAttributeEnabled(editable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class XpressNet : public SubObject
|
|||||||
|
|
||||||
Property<XpressNetCommandStation> commandStation;
|
Property<XpressNetCommandStation> commandStation;
|
||||||
Property<bool> useEmergencyStopLocomotiveCommand;
|
Property<bool> useEmergencyStopLocomotiveCommand;
|
||||||
Property<bool> useFunctionStateCommands;
|
//Property<bool> useFunctionStateCommands;
|
||||||
Property<bool> useRocoF13F20Command;
|
Property<bool> useRocoF13F20Command;
|
||||||
Property<bool> debugLog;
|
Property<bool> debugLog;
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include "../world/world.hpp"
|
#include "../world/world.hpp"
|
||||||
#include "../enum/worldevent.hpp"
|
#include "../enum/worldevent.hpp"
|
||||||
#include "../set/worldstate.hpp"
|
#include "../set/worldstate.hpp"
|
||||||
|
#include "../core/attributes.hpp"
|
||||||
|
|
||||||
namespace Lua {
|
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(name);
|
||||||
m_interfaceItems.add(active);
|
m_interfaceItems.add(active);
|
||||||
m_interfaceItems.add(code)
|
Attributes::addEnabled(code, !active && editable);
|
||||||
.addAttributeEnabled(!active && editable);
|
m_interfaceItems.add(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::addToWorld()
|
void Script::addToWorld()
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "scriptlist.hpp"
|
#include "scriptlist.hpp"
|
||||||
#include "scriptlisttablemodel.hpp"
|
#include "scriptlisttablemodel.hpp"
|
||||||
#include "../world/getworld.hpp"
|
#include "../world/getworld.hpp"
|
||||||
|
#include "../core/attributes.hpp"
|
||||||
|
|
||||||
namespace Lua {
|
namespace Lua {
|
||||||
|
|
||||||
@ -42,8 +43,8 @@ ScriptList::ScriptList(Object& _parent, const std::string& parentPropertyName) :
|
|||||||
auto world = getWorld(&_parent);
|
auto world = getWorld(&_parent);
|
||||||
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(add)
|
Attributes::addEnabled(add, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableModelPtr ScriptList::getModel()
|
TableModelPtr ScriptList::getModel()
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "train.hpp"
|
#include "train.hpp"
|
||||||
#include "../world/world.hpp"
|
#include "../world/world.hpp"
|
||||||
#include "trainlisttablemodel.hpp"
|
#include "trainlisttablemodel.hpp"
|
||||||
|
#include "../core/attributes.hpp"
|
||||||
|
|
||||||
Train::Train(const std::weak_ptr<World>& world, std::string_view _id) :
|
Train::Train(const std::weak_ptr<World>& world, std::string_view _id) :
|
||||||
IdObject(world, _id),
|
IdObject(world, _id),
|
||||||
@ -37,13 +38,14 @@ Train::Train(const std::weak_ptr<World>& world, std::string_view _id) :
|
|||||||
auto w = world.lock();
|
auto w = world.lock();
|
||||||
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(name)
|
Attributes::addEnabled(name, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(name);
|
||||||
m_interfaceItems.add(lob);
|
m_interfaceItems.add(lob);
|
||||||
|
Attributes::addValues(direction, DirectionValues);
|
||||||
m_interfaceItems.add(direction);
|
m_interfaceItems.add(direction);
|
||||||
m_interfaceItems.add(speed);
|
m_interfaceItems.add(speed);
|
||||||
m_interfaceItems.add(speedMax)
|
Attributes::addEnabled(speedMax, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(speedMax);
|
||||||
m_interfaceItems.add(throttleSpeed);
|
m_interfaceItems.add(throttleSpeed);
|
||||||
m_interfaceItems.add(weight);
|
m_interfaceItems.add(weight);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "trainlisttablemodel.hpp"
|
#include "trainlisttablemodel.hpp"
|
||||||
#include "../world/world.hpp"
|
#include "../world/world.hpp"
|
||||||
#include "../world/getworld.hpp"
|
#include "../world/getworld.hpp"
|
||||||
|
#include "../core/attributes.hpp"
|
||||||
|
|
||||||
TrainList::TrainList(Object& _parent, const std::string& parentPropertyName) :
|
TrainList::TrainList(Object& _parent, const std::string& parentPropertyName) :
|
||||||
ObjectList<Train>(_parent, parentPropertyName),
|
ObjectList<Train>(_parent, parentPropertyName),
|
||||||
@ -39,8 +40,8 @@ TrainList::TrainList(Object& _parent, const std::string& parentPropertyName) :
|
|||||||
auto world = getWorld(&_parent);
|
auto world = getWorld(&_parent);
|
||||||
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(add)
|
Attributes::addEnabled(add, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableModelPtr TrainList::getModel()
|
TableModelPtr TrainList::getModel()
|
||||||
|
|||||||
60
server/src/utils/json.hpp
Normale Datei
60
server/src/utils/json.hpp
Normale Datei
@ -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
|
||||||
@ -23,8 +23,8 @@
|
|||||||
#include "railvehiclelist.hpp"
|
#include "railvehiclelist.hpp"
|
||||||
#include "railvehiclelisttablemodel.hpp"
|
#include "railvehiclelisttablemodel.hpp"
|
||||||
#include "railvehicles.hpp"
|
#include "railvehicles.hpp"
|
||||||
#include "../../world/world.hpp"
|
|
||||||
#include "../../world/getworld.hpp"
|
#include "../../world/getworld.hpp"
|
||||||
|
#include "../../core/attributes.hpp"
|
||||||
|
|
||||||
RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPropertyName) :
|
RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPropertyName) :
|
||||||
ObjectList<RailVehicle>(_parent, parentPropertyName),
|
ObjectList<RailVehicle>(_parent, parentPropertyName),
|
||||||
@ -40,8 +40,8 @@ RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPrope
|
|||||||
auto world = getWorld(&_parent);
|
auto world = getWorld(&_parent);
|
||||||
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
const bool editable = world && contains(world->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(add)
|
Attributes::addEnabled(add, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(add);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableModelPtr RailVehicleList::getModel()
|
TableModelPtr RailVehicleList::getModel()
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "vehicle.hpp"
|
#include "vehicle.hpp"
|
||||||
#include "../world/world.hpp"
|
#include "../world/world.hpp"
|
||||||
|
#include "../core/attributes.hpp"
|
||||||
|
|
||||||
Vehicle::Vehicle(const std::weak_ptr<World>& world, std::string_view _id) :
|
Vehicle::Vehicle(const std::weak_ptr<World>& world, std::string_view _id) :
|
||||||
IdObject(world, _id),
|
IdObject(world, _id),
|
||||||
@ -30,8 +31,8 @@ Vehicle::Vehicle(const std::weak_ptr<World>& world, std::string_view _id) :
|
|||||||
auto w = world.lock();
|
auto w = world.lock();
|
||||||
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
const bool editable = w && contains(w->state.value(), WorldState::Edit);
|
||||||
|
|
||||||
m_interfaceItems.add(name)
|
Attributes::addEnabled(name, editable);
|
||||||
.addAttributeEnabled(editable);
|
m_interfaceItems.add(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vehicle::worldEvent(WorldState state, WorldEvent event)
|
void Vehicle::worldEvent(WorldState state, WorldEvent event)
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "worldsaver.hpp"
|
#include "worldsaver.hpp"
|
||||||
#include "../core/traintastic.hpp"
|
#include "../core/traintastic.hpp"
|
||||||
#include "../core/objectlisttablemodel.hpp"
|
#include "../core/objectlisttablemodel.hpp"
|
||||||
|
#include "../core/attributes.hpp"
|
||||||
|
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
@ -121,6 +122,7 @@ World::World(Private) :
|
|||||||
m_filename = Traintastic::instance->worldDir() / to_string(m_uuid) / filename;
|
m_filename = Traintastic::instance->worldDir() / to_string(m_uuid) / filename;
|
||||||
|
|
||||||
m_interfaceItems.add(name);
|
m_interfaceItems.add(name);
|
||||||
|
Attributes::addValues(scale, WorldScaleValues);
|
||||||
m_interfaceItems.add(scale);
|
m_interfaceItems.add(scale);
|
||||||
|
|
||||||
m_interfaceItems.add(commandStations);
|
m_interfaceItems.add(commandStations);
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
#include <boost/uuid/uuid.hpp>
|
#include <boost/uuid/uuid.hpp>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <traintastic/enum/worldevent.hpp>
|
#include <traintastic/enum/worldevent.hpp>
|
||||||
#include <traintastic/enum/worldscale.hpp>
|
#include "../enum/worldscale.hpp"
|
||||||
#include <traintastic/set/worldstate.hpp>
|
#include <traintastic/set/worldstate.hpp>
|
||||||
#include "../clock/clock.hpp"
|
#include "../clock/clock.hpp"
|
||||||
#include "../hardware/commandstation/commandstationlist.hpp"
|
#include "../hardware/commandstation/commandstationlist.hpp"
|
||||||
|
|||||||
34
shared/src/traintastic/enum/attributetype.hpp
Normale Datei
34
shared/src/traintastic/enum/attributetype.hpp
Normale Datei
@ -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
|
||||||
@ -40,4 +40,12 @@ struct EnumName<CommandStationStatus>
|
|||||||
static constexpr char const* value = "command_station_status";
|
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
|
#endif
|
||||||
|
|||||||
@ -30,10 +30,10 @@ enum class DecoderProtocol : uint8_t
|
|||||||
{
|
{
|
||||||
Auto = 0,
|
Auto = 0,
|
||||||
DCC = 1,
|
DCC = 1,
|
||||||
Motorola = 2,
|
//Motorola = 2,
|
||||||
MFX = 3,
|
//MFX = 3,
|
||||||
Selectrix = 4,
|
//Selectrix = 4,
|
||||||
FMZ = 5,
|
//FMZ = 5,
|
||||||
Custom = 255,
|
Custom = 255,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,4 +43,11 @@ struct EnumName<DecoderProtocol>
|
|||||||
static constexpr char const* value = "decoder_protocol";
|
static constexpr char const* value = "decoder_protocol";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ENUM_VALUES(DecoderProtocol, 3,
|
||||||
|
{
|
||||||
|
{DecoderProtocol::Auto, "AUTO"},
|
||||||
|
{DecoderProtocol::DCC, "DCC"},
|
||||||
|
{DecoderProtocol::Custom, "CUSTOM"},
|
||||||
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -38,4 +38,10 @@ struct EnumName<Direction>
|
|||||||
static constexpr char const* value = "direction";
|
static constexpr char const* value = "direction";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ENUM_VALUES(Direction, 2,
|
||||||
|
{
|
||||||
|
{Direction::Forward, "forward"},
|
||||||
|
{Direction::Reverse, "reverse"},
|
||||||
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -24,10 +24,32 @@
|
|||||||
#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ENUM_HPP
|
#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ENUM_HPP
|
||||||
#define 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>
|
template<typename T>
|
||||||
struct EnumName
|
struct EnumName
|
||||||
{
|
{
|
||||||
static_assert(sizeof(T) != sizeof(T), "template specialization required");
|
static_assert(sizeof(T) != sizeof(T), "template specialization required");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct EnumValues
|
||||||
|
{
|
||||||
|
static_assert(sizeof(T) != sizeof(T), "template specialization required");
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -41,4 +41,14 @@ struct EnumName<LengthUnit>
|
|||||||
static constexpr char const* value = "length_unit";
|
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
|
#endif
|
||||||
|
|||||||
@ -25,18 +25,22 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "enum.hpp"
|
#include "enum.hpp"
|
||||||
|
#include <frozen/map.h>
|
||||||
|
|
||||||
enum class LocoNetCommandStation : uint16_t
|
enum class LocoNetCommandStation : uint16_t
|
||||||
{
|
{
|
||||||
Custom = 0,
|
Custom = 0,
|
||||||
UhlenbrockIntellibox = 1,
|
UhlenbrockIntellibox = 1,
|
||||||
DigiKeijsDR5000 = 2,
|
DigikeijsDR5000 = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
ENUM_NAME(LocoNetCommandStation, "loconet_command_station")
|
||||||
struct EnumName<LocoNetCommandStation>
|
|
||||||
|
ENUM_VALUES(LocoNetCommandStation, 3,
|
||||||
{
|
{
|
||||||
static constexpr char const* value = "loconet_command_station";
|
{LocoNetCommandStation::Custom, "custom"},
|
||||||
};
|
{LocoNetCommandStation::UhlenbrockIntellibox, "uhlenbrock_intellibox"},
|
||||||
|
{LocoNetCommandStation::DigikeijsDR5000, "digikeijs_dr5000"},
|
||||||
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -29,14 +29,17 @@
|
|||||||
enum class LocoNetSerialInterface : uint16_t
|
enum class LocoNetSerialInterface : uint16_t
|
||||||
{
|
{
|
||||||
Custom = 0,
|
Custom = 0,
|
||||||
DigiKeijsDR5000 = 1,
|
DigikeijsDR5000 = 1,
|
||||||
RoSoftLocoNetInterface = 2,
|
RoSoftLocoNetInterface = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
ENUM_NAME(LocoNetSerialInterface, "loconet_serial_interface")
|
||||||
struct EnumName<LocoNetSerialInterface>
|
|
||||||
|
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
|
#endif
|
||||||
|
|||||||
@ -20,30 +20,8 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_SERIALFLOWCONTROL_HPP
|
||||||
* shared/src/enum/serialflowcontrol.hpp
|
#define TRAINTASTIC_SHARED_TRAINTASTIC_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
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include "enum.hpp"
|
#include "enum.hpp"
|
||||||
@ -54,10 +32,12 @@ enum class SerialFlowControl : uint8_t
|
|||||||
Hardware = 1,
|
Hardware = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
ENUM_NAME(SerialFlowControl, "serial_flow_control")
|
||||||
struct EnumName<SerialFlowControl>
|
|
||||||
|
ENUM_VALUES(SerialFlowControl, 2,
|
||||||
{
|
{
|
||||||
static constexpr char const* value = "serial_flow_control";
|
{SerialFlowControl::None, "none"},
|
||||||
};
|
{SerialFlowControl::Hardware, "hardware"},
|
||||||
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -38,4 +38,11 @@ struct EnumName<SpeedUnit>
|
|||||||
static constexpr char const* value = "speed_unit";
|
static constexpr char const* value = "speed_unit";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ENUM_VALUES(SpeedUnit, 3,
|
||||||
|
{
|
||||||
|
{SpeedUnit::MeterPerSecond, "mps"},
|
||||||
|
{SpeedUnit::KiloMeterPerHour, "kmph"},
|
||||||
|
{SpeedUnit::MilePerHour, "mph"},
|
||||||
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -39,4 +39,12 @@ struct EnumName<WeightUnit>
|
|||||||
static constexpr char const* value = "weight_unit";
|
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
|
#endif
|
||||||
|
|||||||
@ -43,4 +43,15 @@ struct EnumName<WorldEvent>
|
|||||||
static constexpr char const* value = "world_event";
|
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
|
#endif
|
||||||
|
|||||||
@ -41,4 +41,13 @@ struct EnumName<WorldScale>
|
|||||||
static constexpr char const* value = "world_scale";
|
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
|
#endif
|
||||||
|
|||||||
@ -30,6 +30,7 @@ enum class XpressNetCommandStation : uint16_t
|
|||||||
{
|
{
|
||||||
Custom = 0,
|
Custom = 0,
|
||||||
Roco10764 = 1,
|
Roco10764 = 1,
|
||||||
|
DigikeijsDR5000 = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -38,4 +39,11 @@ struct EnumName<XpressNetCommandStation>
|
|||||||
static constexpr char const* value = "xpressnet_command_station";
|
static constexpr char const* value = "xpressnet_command_station";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ENUM_VALUES(XpressNetCommandStation, 3,
|
||||||
|
{
|
||||||
|
{XpressNetCommandStation::Custom, "custom"},
|
||||||
|
{XpressNetCommandStation::Roco10764, "roco_10764"},
|
||||||
|
{XpressNetCommandStation::DigikeijsDR5000, "digikeijs_dr5000"},
|
||||||
|
})
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -41,4 +41,13 @@ struct EnumName<XpressNetSerialInterface>
|
|||||||
static constexpr char const* value = "xpressnet_serial_interface";
|
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
|
#endif
|
||||||
|
|||||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren