diff --git a/client/src/network/connection.cpp b/client/src/network/connection.cpp index f30fdcd4..1200b8db 100644 --- a/client/src/network/connection.cpp +++ b/client/src/network/connection.cpp @@ -31,6 +31,7 @@ #include "method.hpp" #include "tablemodel.hpp" #include +#include #include //#include //#include @@ -371,35 +372,87 @@ ObjectPtr Connection::readObject(const Message& message) { message.readBlock(); // item const AttributeName attributeName = message.read(); - QVariant value; - switch(message.read()) + const ValueType type = message.read(); + + switch(message.read()) { - case ValueType::Boolean: - value = message.read(); - break; + case AttributeType::Value: + { + QVariant value; + switch(type) + { + case ValueType::Boolean: + value = message.read(); + break; - case ValueType::Enum: - case ValueType::Integer: - value = message.read(); - break; + case ValueType::Enum: + case ValueType::Integer: + value = message.read(); + break; - case ValueType::Float: - value = message.read(); - break; + case ValueType::Float: + value = message.read(); + break; - case ValueType::String: - value = QString::fromUtf8(message.read()); - break; + case ValueType::String: + value = QString::fromUtf8(message.read()); + break; - case ValueType::Object: - case ValueType::Invalid: + case ValueType::Object: + case ValueType::Invalid: + default: + Q_ASSERT(false); + break; + } + if(Q_LIKELY(value.isValid())) + item->m_attributes[attributeName] = value; + break; + } + case AttributeType::Values: + { + const int length = message.read(); // read uint32_t as int, Qt uses int for length + QList values; + switch(type) + { + case ValueType::Boolean: + { + for(int i = 0; i < length; i++) + values.append(message.read()); + break; + } + case ValueType::Enum: + case ValueType::Integer: + { + for(int i = 0; i < length; i++) + values.append(message.read()); + break; + } + case ValueType::Float: + { + for(int i = 0; i < length; i++) + values.append(message.read()); + break; + } + case ValueType::String: + { + for(int i = 0; i < length; i++) + values.append(QString::fromUtf8(message.read())); + 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); - break; } - - if(Q_LIKELY(value.isValid())) - item->m_attributes[attributeName] = value; - message.readBlockEnd(); // end attribute } message.readBlockEnd(); // end attributes diff --git a/client/src/utils/internalupdateholder.hpp b/client/src/utils/internalupdateholder.hpp new file mode 100644 index 00000000..a2213c02 --- /dev/null +++ b/client/src/utils/internalupdateholder.hpp @@ -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 diff --git a/client/src/utils/translateenum.cpp b/client/src/utils/translateenum.cpp new file mode 100644 index 00000000..a10df94e --- /dev/null +++ b/client/src/utils/translateenum.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/client/src/utils/translateenum.hpp b/client/src/utils/translateenum.hpp new file mode 100644 index 00000000..fe5e1b45 --- /dev/null +++ b/client/src/utils/translateenum.hpp @@ -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 translateEnum(const QString& enumName, qint64 value); + +#endif diff --git a/client/src/widget/propertycheckbox.cpp b/client/src/widget/propertycheckbox.cpp index b17529d3..cedced97 100644 --- a/client/src/widget/propertycheckbox.cpp +++ b/client/src/widget/propertycheckbox.cpp @@ -22,26 +22,7 @@ #include "propertycheckbox.hpp" #include "../network/property.hpp" - -class InternalUpdateHolder -{ - private: - bool& m_value; - - public: - inline InternalUpdateHolder(bool& value) : - m_value{value} - { - Q_ASSERT(!m_value); - m_value = true; - } - - inline ~InternalUpdateHolder() - { - Q_ASSERT(m_value); - m_value = false; - } -}; +#include "../utils/internalupdateholder.hpp" PropertyCheckBox::PropertyCheckBox(Property& property, QWidget* parent) : QCheckBox(parent), diff --git a/client/src/widget/propertycombobox.cpp b/client/src/widget/propertycombobox.cpp index c55a66c1..93e8220f 100644 --- a/client/src/widget/propertycombobox.cpp +++ b/client/src/widget/propertycombobox.cpp @@ -22,21 +22,25 @@ #include "propertycombobox.hpp" #include "../network/property.hpp" +#include "../utils/internalupdateholder.hpp" +#include "../utils/translateenum.hpp" PropertyComboBox::PropertyComboBox(Property& property, QWidget* parent) : QComboBox(parent), - m_property{property} + m_property{property}, + m_internalUpdate{false} { Q_ASSERT(m_property.type() == ValueType::Enum); setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true)); setVisible(m_property.getAttributeBool(AttributeName::Visible, true)); - //setChecked(m_property.toBool()); - //connect(&m_property, &Property::valueChangedBool, - // [this](bool value) - // { - // InternalUpdateHolder hold(m_internalUpdate); - // setChecked(value); - // }); + + connect(&m_property, &Property::valueChangedInt64, + [this](qint64 value) + { + InternalUpdateHolder hold(m_internalUpdate); + if(int index = findData(value); index != -1) + setCurrentIndex(index); + }); connect(&m_property, &Property::attributeChanged, [this](AttributeName name, const QVariant& value) { @@ -50,14 +54,43 @@ PropertyComboBox::PropertyComboBox(Property& property, QWidget* parent) : setVisible(value.toBool()); break; + case AttributeName::Values: + updateValues(); + break; + default: break; } }); - //connect(this, &PropertyCheckBox::toggled, - // [this](bool value) - // { - // if(!m_internalUpdate) - // m_property.setValueBool(value); - // }); + connect(this, static_cast(&PropertyComboBox::currentIndexChanged), + [this](int) + { + if(!m_internalUpdate) + if(QVariant v = currentData(); v.canConvert()) + 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); + } + } + } } diff --git a/client/src/widget/propertycombobox.hpp b/client/src/widget/propertycombobox.hpp index 35ea07e5..a530d639 100644 --- a/client/src/widget/propertycombobox.hpp +++ b/client/src/widget/propertycombobox.hpp @@ -29,8 +29,13 @@ class Property; class PropertyComboBox : public QComboBox { + Q_OBJECT + protected: Property& m_property; + bool m_internalUpdate; + + void updateValues(); public: PropertyComboBox(Property& property, QWidget* parent = nullptr); diff --git a/client/traintastic-client.pro b/client/traintastic-client.pro index a92cc5c6..67076795 100644 --- a/client/traintastic-client.pro +++ b/client/traintastic-client.pro @@ -13,6 +13,7 @@ greaterThan(QT_MINOR_VERSION, 11): { # >= 5.12 INCLUDEPATH += \ ../shared/src \ + ../server/thirdparty \ thirdparty SOURCES += \ @@ -51,7 +52,8 @@ SOURCES += \ src/network/connection.cpp \ src/mdiarea.cpp \ src/network/method.cpp \ - src/dialog/worldlistdialog.cpp + src/dialog/worldlistdialog.cpp \ + src/utils/translateenum.cpp HEADERS += \ src/mainwindow.hpp \ @@ -93,7 +95,9 @@ HEADERS += \ src/network/connection.hpp \ src/mdiarea.hpp \ src/network/method.hpp \ - src/dialog/worldlistdialog.hpp + src/dialog/worldlistdialog.hpp \ + src/utils/translateenum.hpp \ + src/utils/internalupdateholder.hpp RESOURCES += \ dark.qrc diff --git a/lang/en-us.txt b/lang/en-us.txt index 8f83be24..e7edf81e 100644 --- a/lang/en-us.txt +++ b/lang/en-us.txt @@ -1,19 +1,19 @@ ## Traintastic language file: English (US) :address=Address +:baudrate=Baudrate :command_station=Command station :controllers=Controllers +:decoders=Decoders :emergency_stop=Emergency stop :id=Id +:loconet=LocoNet :name=Name :notes=Notes -:track_power=Track power :online=Online :port=Port +:track_power=Track power :xpressnet=XpressNet -:loconet=LocoNet -:baudrate=Baudrate -:decoders=Decoders clock:day=Day clock:hour=Hour @@ -22,48 +22,71 @@ clock:month=Month clock:multiplier=Multiplier clock:year=Year +command_station.loconet_serial:flow_control=Flow control +command_station.loconet_serial:interface=Interface + +command_station.z21:filtered_main_current=Filtered main current +command_station.z21:firmware_version=Firmware version +command_station.z21:hardware_type=Hardware type +command_station.z21:high_temperature=High temperature +command_station.z21:hostname=Hostname +command_station.z21:main_current=Main current +command_station.z21:power_lost=Power lost +command_station.z21:prog_current=Prog current +command_station.z21:programming_mode_active=Programming mode active +command_station.z21:serial_number=Serial number +command_station.z21:short_circuit=Short circuit +command_station.z21:short_circut_external=Short circut external +command_station.z21:short_circut_internal=Short circut internal +command_station.z21:supply_voltage=Supply voltage +command_station.z21:temperature=Temperature +command_station.z21:vcc_voltage=VCC voltage + +command_station_list:add=Add +command_station_list:remove=Remove + +console:level=Level +console:message=Message +console:object=Object +console:time=Time + +controller.z21_app:active=Active + +controller:active=Active + +controller_list:add=Add + +decoder:direction=Direction +decoder:functions=Functions +decoder:long_address=Long address +decoder:protocol=Protocol +decoder:speed_step=Speed step +decoder:speed_steps=Speed steps + +decoder_function:id=Id +decoder_function:momentary=Momentary +decoder_function:number=Number +decoder_function:value=Value + decoder_function_list:add=Add function +decoder_function_list:f_hash=F# decoder_list:add=Add -hardware.command_station.z21:filtered_main_current=Filtered main current -hardware.command_station.z21:firmware_version=Firmware version -hardware.command_station.z21:hardware_type=Hardware type -hardware.command_station.z21:high_temperature=High temperature -hardware.command_station.z21:hostname=Hostname -hardware.command_station.z21:main_current=Main current -hardware.command_station.z21:power_lost=Power lost -hardware.command_station.z21:prog_current=Prog current -hardware.command_station.z21:programming_mode_active=Programming mode active -hardware.command_station.z21:serial_number=Serial number -hardware.command_station.z21:short_circuit=Short circuit -hardware.command_station.z21:short_circut_external=Short circut external -hardware.command_station.z21:short_circut_internal=Short circut internal -hardware.command_station.z21:supply_voltage=Supply voltage -hardware.command_station.z21:temperature=Temperature -hardware.command_station.z21:vcc_voltage=VCC voltage - -hardware.controller.z21_app:active=Active - -hardware.controller:active=Active - -hardware.decoder:direction=Direction -hardware.decoder:functions=Functions -hardware.decoder:protocol=Protocol -hardware.decoder:speed_step=Speed step -hardware.decoder:speed_steps=Speed steps - -hardware.decoder_function:id=Id -hardware.decoder_function:momentary=Momentary -hardware.decoder_function:number=Number -hardware.decoder_function:value=Value - -hardware.decoder_function_list:f_hash=F# - language:de-de=German language:en-us=English (US) language:nl-nl=Dutch +list.train:add=Create train + +loconet_command_station:custom=Custom +loconet_command_station:digikeijs_dr5000=Digikeijs DR5000 +loconet_command_station:uhlenbrock_intellibox=Uhlenbrock Intellibox + +loconet_serial_interface:custom=Custom +loconet_serial_interface:digikeijs_dr5000=Digikeijs DR5000 +loconet_serial_interface:rosoft_loconet_interface=RoSoft LocoNet interface + lua.script:active=Active lua.script:code=Code @@ -102,15 +125,22 @@ qtapp.mainmenu:settings=Settings qtapp.mainmenu:tools=Tools qtapp.mainmenu:view=View -qtapp.world_list_dialog:world_list=World list -qtapp.world_list_dialog:load=Load qtapp.world_list_dialog:cancel=Cancel -world_list:uuid=UUID +qtapp.world_list_dialog:load=Load +qtapp.world_list_dialog:world_list=World list + +serial_flow_control:hardware=Hardware +serial_flow_control:none=None settings:default_world=Default world settings:localhost_only=Localhost only settings:port=Port +train:lob=LOB +train:speed=Speed +train:throttle_speed=Throttle speed +train:weight=Weight + world:clock=Clock world:command_stations=Command stations world:decoders=Decoders @@ -118,21 +148,15 @@ world:edit=Edit world world:emergency_stop=Emergency stop world:inputs=Inputs world:lua_scripts=Lua scripts +world:rail_vehicles=Rail vehicles world:scale=Scale world:track_power_off=Track power off world:track_power_on=Track power on -world:rail_vehicles=Rail vehicles - - -console:message=Message -console:time=Time -console:level=Level -console:object=Object - world:trains=Trains -list.train:add=Create train -train:lob=LOB -train:speed=Speed + +world_list:uuid=UUID + + +#! Garbage +#! Garbage train:speedMax=Maximum speed -train:throttle_speed=Throttle speed -train:weight=Weight diff --git a/lang/nl-nl.txt b/lang/nl-nl.txt index f4ab5f76..efaae0b4 100644 --- a/lang/nl-nl.txt +++ b/lang/nl-nl.txt @@ -32,6 +32,8 @@ hardware.decoder:speed_steps=Snelheid stappen hardware.decoder_function:number=Nummer hardware.decoder_function:value=Waarde +hardware.decoder_function_list:f_hash=F# + language:de-de=Duits language:en-us=Engels (VS) language:nl-nl=Nederlands @@ -53,7 +55,6 @@ qtapp.connect_dialog:server=Server qtapp.connect_dialog:username=Gebruikersnaam qtapp.mainmenu:about=Over -qtapp.mainmenu:settings=Instellingen qtapp.mainmenu:connect_to_server=Verbind met server qtapp.mainmenu:disconnect_from_server=Verbreek verbinding met server qtapp.mainmenu:export_world=Wereld exporteren @@ -69,6 +70,7 @@ qtapp.mainmenu:quit=Afsluiten qtapp.mainmenu:save_world=Wereld opslaan qtapp.mainmenu:server_console=Server console qtapp.mainmenu:server_settings=Server instellingen +qtapp.mainmenu:settings=Instellingen qtapp.mainmenu:tools=Extra qtapp.mainmenu:view=Beeld @@ -83,10 +85,3 @@ world:lua_scripts=Lua scripts world:scale=Schaal world:track_power_off=Railspanning uit world:track_power_on=Railspanning aan - - - - -hardware.decoder_function_list:f_hash=F# - - diff --git a/server/ideas.md b/server/ideas.md index 91720506..3da6ea74 100644 --- a/server/ideas.md +++ b/server/ideas.md @@ -24,7 +24,20 @@ WeightProperty - decoder2 +# train +- trothlle speed +- weight simulation: 0=off, 1=real, 2=half +# netwerk +enum als string over netwerk?? nummers zijn dan alleen intern, niet in json/netwerk + +# controller usb xpressnet interface +- allow estop +- allow power off +- mode: + - direct: multimaus decoder addr == decoder addr + - virtual decoder: multimaus decoder addr = assigend decoder addr + - virtual maus: multimaus addr = assigend decoder addr # task thread diff --git a/server/src/core/abstractattribute.cpp b/server/src/core/abstractattribute.cpp index bfbdd129..df276958 100644 --- a/server/src/core/abstractattribute.cpp +++ b/server/src/core/abstractattribute.cpp @@ -24,10 +24,10 @@ #include "interfaceitem.hpp" #include "object.hpp" -AbstractAttribute::AbstractAttribute(InterfaceItem& item, AttributeName name, ValueType type) : - m_item{item}, - m_name{name}, - m_type{type} +AbstractAttribute::AbstractAttribute(InterfaceItem& _item, AttributeName _name, ValueType _type) : + m_item{_item}, + m_name{_name}, + m_type{_type} { } diff --git a/server/src/core/abstractattribute.hpp b/server/src/core/abstractattribute.hpp index a0be3dbc..0fe53197 100644 --- a/server/src/core/abstractattribute.hpp +++ b/server/src/core/abstractattribute.hpp @@ -39,16 +39,12 @@ class AbstractAttribute void changed(); public: - AbstractAttribute(InterfaceItem& item, AttributeName name, ValueType type); + AbstractAttribute(InterfaceItem& _item, AttributeName _name, ValueType _type); + virtual ~AbstractAttribute() = default; inline InterfaceItem& item() const { return m_item; } inline AttributeName name() const { return m_name; } inline ValueType type() const { return m_type; } - - virtual bool toBool() const = 0; - virtual int64_t toInt64() const = 0; - virtual double toDouble() const = 0; - virtual std::string toString() const = 0; }; #endif diff --git a/server/src/core/abstractproperty.hpp b/server/src/core/abstractproperty.hpp index ac4ac11f..35456365 100644 --- a/server/src/core/abstractproperty.hpp +++ b/server/src/core/abstractproperty.hpp @@ -28,7 +28,7 @@ #include #include "objectptr.hpp" #include -#include +#include "../utils/json.hpp" class AbstractProperty : public InterfaceItem { diff --git a/server/src/core/abstractvalueattribute.hpp b/server/src/core/abstractvalueattribute.hpp new file mode 100644 index 00000000..3adcd312 --- /dev/null +++ b/server/src/core/abstractvalueattribute.hpp @@ -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 diff --git a/server/src/core/abstractvaluesattribute.hpp b/server/src/core/abstractvaluesattribute.hpp new file mode 100644 index 00000000..2b4c2321 --- /dev/null +++ b/server/src/core/abstractvaluesattribute.hpp @@ -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 diff --git a/server/src/core/arrayattribute.hpp b/server/src/core/arrayattribute.hpp new file mode 100644 index 00000000..92287762 --- /dev/null +++ b/server/src/core/arrayattribute.hpp @@ -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 +#include "abstractvaluesattribute.hpp" +#include "to.hpp" + +template +class ArrayAttribute : public AbstractValuesAttribute +{ + protected: + const std::array& m_values; + + public: + ArrayAttribute(InterfaceItem& _item, AttributeName _name, const std::array& values) : + AbstractValuesAttribute(_item, _name, value_type_v), + m_values{values} + { + static_assert(value_type_v != 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(m_values[index]); + } + + virtual int64_t getInt64(uint32_t index) const final + { + assert(index < length()); + return to(m_values[index]); + } + + virtual double getDouble(uint32_t index) const final + { + assert(index < length()); + return to(m_values[index]); + } + + virtual std::string getString(uint32_t index) const final + { + assert(index < length()); + return to(m_values[index]); + } +}; + +#endif diff --git a/server/src/core/attribute.hpp b/server/src/core/attribute.hpp index a1a6c083..d2bf3827 100644 --- a/server/src/core/attribute.hpp +++ b/server/src/core/attribute.hpp @@ -23,21 +23,22 @@ #ifndef TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP #define TRAINTASTIC_SERVER_CORE_ATTRIBUTE_HPP -#include "abstractattribute.hpp" +#include "abstractvalueattribute.hpp" #include "to.hpp" #include "valuetypetraits.hpp" template -class Attribute : public AbstractAttribute +class Attribute : public AbstractValueAttribute { protected: T m_value; public: Attribute(InterfaceItem& item, AttributeName name, const T& value) : - AbstractAttribute{item, name, value_type_v}, + AbstractValueAttribute{item, name, value_type_v}, m_value{value} { + static_assert(value_type_v != ValueType::Invalid); } bool toBool() const final diff --git a/server/src/core/attributes.hpp b/server/src/core/attributes.hpp new file mode 100644 index 00000000..605b7fc2 --- /dev/null +++ b/server/src/core/attributes.hpp @@ -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 + static inline void addValues(Property& property, const std::array& values) + { + property.addAttribute(AttributeName::Values, values); + } + + +//inline InterfaceItem& addAttributeSubObject(bool value) { return addAttribute(AttributeName::SubObject, value); } +/* +template +inline InterfaceItem& addAttributeValues(const std::array& values) { return addAttribute(AttributeName::Values, values); } +*/ +}; + +#endif diff --git a/server/src/core/idobject.cpp b/server/src/core/idobject.cpp index ed5f20f1..a8460589 100644 --- a/server/src/core/idobject.cpp +++ b/server/src/core/idobject.cpp @@ -21,7 +21,8 @@ #include "idobject.hpp" #include "traintastic.hpp" #include "console.hpp" -#include "../world/world.hpp" +#include "../world/getworld.hpp" +#include "attributes.hpp" IdObject::IdObject(const std::weak_ptr& world, std::string_view _id) : Object{}, @@ -29,7 +30,10 @@ IdObject::IdObject(const std::weak_ptr& world, std::string_view _id) : id{this, "id", std::string(_id.data(), _id.size()), PropertyFlags::ReadWrite | PropertyFlags::Store, nullptr, [this](std::string& value) { - auto& m = Traintastic::instance->world->m_objects; + auto w = getWorld(this); + if(!w) + return false; + auto& m = w->m_objects; if(m.find(value) != m.end()) return false; auto n = m.extract(id); @@ -41,8 +45,8 @@ IdObject::IdObject(const std::weak_ptr& world, std::string_view _id) : auto w = world.lock(); const bool editable = w && contains(w->state.value(), WorldState::Edit); - m_interfaceItems.add(id) - .addAttributeEnabled(editable); + Attributes::addEnabled(id, editable); + m_interfaceItems.add(id); } IdObject::~IdObject() diff --git a/server/src/core/interfaceitem.hpp b/server/src/core/interfaceitem.hpp index 6beef175..2a92d26c 100644 --- a/server/src/core/interfaceitem.hpp +++ b/server/src/core/interfaceitem.hpp @@ -27,12 +27,15 @@ #include #include #include "attribute.hpp" +#include "arrayattribute.hpp" #include class Object; class InterfaceItem { + friend struct Attributes; + public: using Attributes = std::unordered_map>; @@ -42,10 +45,15 @@ class InterfaceItem Attributes m_attributes; template - InterfaceItem& addAttribute(AttributeName name, const T& value) + void addAttribute(AttributeName name, const T& value) { m_attributes.emplace(name, std::make_unique>(*this, name, value)); - return *this; + } + + template + void addAttribute(AttributeName name, const std::array& values) + { + m_attributes.emplace(name, std::make_unique>(*this, name, values)); } template @@ -80,15 +88,6 @@ class InterfaceItem return m_attributes; } - inline InterfaceItem& addAttributeCategory(Category value) { return addAttribute(AttributeName::Category, value); } - inline InterfaceItem& addAttributeEnabled(bool value) { return addAttribute(AttributeName::Enabled, value); } - inline InterfaceItem& addAttributeVisible(bool value) { return addAttribute(AttributeName::Visible, value); } - inline InterfaceItem& addAttributeObjectEditor(bool value) { return addAttribute(AttributeName::ObjectEditor, value); } - inline InterfaceItem& addAttributeSubObject(bool value) { return addAttribute(AttributeName::SubObject, value); } - - template - inline InterfaceItem& addAttributeValues(const std::array& values) { return addAttribute(AttributeName::Values, values); } - inline void setAttributeEnabled(bool value) { setAttribute(AttributeName::Enabled, value); } }; diff --git a/server/src/core/interfaceitems.cpp b/server/src/core/interfaceitems.cpp index 44ac39ab..f1f49d6c 100644 --- a/server/src/core/interfaceitems.cpp +++ b/server/src/core/interfaceitems.cpp @@ -24,22 +24,39 @@ #include "interfaceitem.hpp" #include +#ifndef NDEBUG +#include "abstractproperty.hpp" + +static void check(const InterfaceItem& item) +{ + if(const AbstractProperty* property = dynamic_cast(&item)) + { + if(property->type() == ValueType::Enum) + assert(property->attributes().find(AttributeName::Values) != property->attributes().cend()); // enum property must have a Values attribute + } +} +#endif + InterfaceItem* InterfaceItems::find(const std::string& name) const { auto it = m_items.find(name); return (it != m_items.end()) ? &it->second : nullptr; } -InterfaceItem& InterfaceItems::add(InterfaceItem& item) +void InterfaceItems::add(InterfaceItem& item) { +#ifndef NDEBUG + check(item); +#endif m_items.emplace(item.name(), item); m_itemOrder.push_back(item.name()); - return item; } -InterfaceItem& InterfaceItems::insertBefore(InterfaceItem& item, const InterfaceItem& before) +void InterfaceItems::insertBefore(InterfaceItem& item, const InterfaceItem& before) { +#ifndef NDEBUG + check(item); +#endif m_items.emplace(item.name(), item); m_itemOrder.insert(std::find(m_itemOrder.begin(), m_itemOrder.end(), before.name()), item.name()); - return item; } diff --git a/server/src/core/interfaceitems.hpp b/server/src/core/interfaceitems.hpp index 2ed19de6..be087830 100644 --- a/server/src/core/interfaceitems.hpp +++ b/server/src/core/interfaceitems.hpp @@ -45,8 +45,8 @@ class InterfaceItems InterfaceItem* find(const std::string& name) const; - InterfaceItem& add(InterfaceItem& item); - InterfaceItem& insertBefore(InterfaceItem& item, const InterfaceItem& before); + void add(InterfaceItem& item); + void insertBefore(InterfaceItem& item, const InterfaceItem& before); inline InterfaceItem& operator[](const std::string& name) const { return m_items.at(name); } }; diff --git a/server/src/core/session.cpp b/server/src/core/session.cpp index 590c19ab..b517d115 100644 --- a/server/src/core/session.cpp +++ b/server/src/core/session.cpp @@ -26,8 +26,10 @@ #include "traintastic.hpp" #include "client.hpp" #include "abstractproperty.hpp" -#include "abstractattribute.hpp" +#include "abstractvalueattribute.hpp" +#include "abstractvaluesattribute.hpp" #include +#include #include "tablemodel.hpp" #include "../world/world.hpp" #include "idobject.hpp" @@ -434,31 +436,7 @@ void Session::writeObject(Message& message, const ObjectPtr& object) { const AbstractAttribute& attribute = *it.second; message.writeBlock(); // attribute - message.write(attribute.name()); - message.write(attribute.type()); - switch(attribute.type()) - { - case ValueType::Boolean: - message.write(attribute.toBool()); - break; - - case ValueType::Enum: - case ValueType::Integer: - message.write(attribute.toInt64()); - break; - - case ValueType::Float: - message.write(attribute.toDouble()); - break; - - case ValueType::String: - message.write(attribute.toString()); - break; - - default: - assert(false); - break; - } + writeAttribute(message, attribute); message.writeBlockEnd(); // end attribute } @@ -547,6 +525,8 @@ void Session::objectAttributeChanged(AbstractAttribute& attribute) auto event = Message::newEvent(Message::Command::ObjectAttributeChanged); event->write(m_handles.getHandle(attribute.item().object().shared_from_this())); event->write(attribute.item().name()); + writeAttribute(*event, attribute); + /* event->write(attribute.name()); event->write(attribute.type()); switch(attribute.type()) @@ -568,5 +548,74 @@ void Session::objectAttributeChanged(AbstractAttribute& attribute) //event->write(attribute.toString()); break; } + */ m_client->sendMessage(std::move(event)); } + +void Session::writeAttribute(Message& message , const AbstractAttribute& attribute) +{ + message.write(attribute.name()); + message.write(attribute.type()); + if(const AbstractValueAttribute* valueAttribute = dynamic_cast(&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(&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); +} diff --git a/server/src/core/session.hpp b/server/src/core/session.hpp index f8081504..29cae7a5 100644 --- a/server/src/core/session.hpp +++ b/server/src/core/session.hpp @@ -39,6 +39,9 @@ class Session : public std::enable_shared_from_this { friend class Client; + private: + static void writeAttribute(Message& message , const AbstractAttribute& attribute); + protected: using Handle = uint32_t; using Handles = HandleList; diff --git a/server/src/core/to.hpp b/server/src/core/to.hpp index 0d700a13..230583d3 100644 --- a/server/src/core/to.hpp +++ b/server/src/core/to.hpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include "../utils/json.hpp" class not_writable_error : public std::runtime_error { @@ -101,11 +101,16 @@ To to(const From& value) } else if constexpr(std::is_same_v) { - // if constexpr(std::is_same_v) - return value;//.get(); + if constexpr(std::is_enum_v) + { + To e; + from_json(value, e); + return e; + } + else + return value; } - throw conversion_error(); } diff --git a/server/src/core/unitproperty.hpp b/server/src/core/unitproperty.hpp index c4dc1da2..76dd33db 100644 --- a/server/src/core/unitproperty.hpp +++ b/server/src/core/unitproperty.hpp @@ -165,7 +165,7 @@ class UnitProperty : public AbstractProperty//InterfaceItem void load(const nlohmann::json& value) final { m_value = to(value["value"]); - m_unit = value["unit"]; + from_json(value["unit"], m_unit); } void load(const ObjectPtr& value) final diff --git a/server/src/core/vectorattribute.hpp b/server/src/core/vectorattribute.hpp index dd14dc5d..27875d2a 100644 --- a/server/src/core/vectorattribute.hpp +++ b/server/src/core/vectorattribute.hpp @@ -31,16 +31,12 @@ template class VectorAttribute : public AbstractAttribute { protected: - std::vector m_value; + std::vector m_values; public: - - -//dsjfnkjdnvjkdnkvjf - - Attribute(InterfaceItem& item, AttributeName name, const T& value) : + VectorAttribute(InterfaceItem& item, AttributeName name, const T& values) : AbstractAttribute{item, name, value_type_v}, - m_value{value} + m_value{values} { } diff --git a/server/src/enum/commandstationstatus.hpp b/server/src/enum/commandstationstatus.hpp index 1ae28a8d..f0d765d0 100644 --- a/server/src/enum/commandstationstatus.hpp +++ b/server/src/enum/commandstationstatus.hpp @@ -29,14 +29,6 @@ #include "../lua/enumvalues.hpp" #endif -NLOHMANN_JSON_SERIALIZE_ENUM(CommandStationStatus, -{ - {CommandStationStatus::Offline, "offline"}, - {CommandStationStatus::Initializing, "initializing"}, - {CommandStationStatus::Online, "online"}, - {CommandStationStatus::Error, "error"}, -}) - #ifndef DISABLE_LUA_SCRIPTING LUA_ENUM_VALUES(CommandStationStatus, 4, { diff --git a/server/src/enum/decoderprotocol.hpp b/server/src/enum/decoderprotocol.hpp index 31e0b23f..a1adbd0f 100644 --- a/server/src/enum/decoderprotocol.hpp +++ b/server/src/enum/decoderprotocol.hpp @@ -29,12 +29,11 @@ #include "../lua/enumvalues.hpp" #endif -NLOHMANN_JSON_SERIALIZE_ENUM(DecoderProtocol, -{ - {DecoderProtocol::Auto, "AUTO"}, - {DecoderProtocol::DCC, "DCC"}, - {DecoderProtocol::Custom, "CUSTOM"}, -}) +inline constexpr std::array DecoderProtocolValues{{ + DecoderProtocol::Auto, + DecoderProtocol::DCC, + DecoderProtocol::Custom, +}}; #ifndef DISABLE_LUA_SCRIPTING LUA_ENUM_VALUES(DecoderProtocol, 3, diff --git a/server/src/enum/direction.hpp b/server/src/enum/direction.hpp index a653cdc6..dbfd29a5 100644 --- a/server/src/enum/direction.hpp +++ b/server/src/enum/direction.hpp @@ -29,11 +29,11 @@ #include "../lua/enumvalues.hpp" #endif -NLOHMANN_JSON_SERIALIZE_ENUM(Direction, -{ - {Direction::Forward, "forward"}, - {Direction::Reverse, "reverse"}, -}) +inline constexpr std::array DirectionValues{{ + Direction::Forward, + Direction::Reverse, +}}; + #ifndef DISABLE_LUA_SCRIPTING LUA_ENUM_VALUES(Direction, 2, diff --git a/server/src/enum/lengthunit.hpp b/server/src/enum/lengthunit.hpp index afe56c63..04d19f8a 100644 --- a/server/src/enum/lengthunit.hpp +++ b/server/src/enum/lengthunit.hpp @@ -24,16 +24,6 @@ #define TRAINTASTIC_SERVER_ENUM_LENGTHUNIT_HPP #include -#include - -NLOHMANN_JSON_SERIALIZE_ENUM(LengthUnit, -{ - {LengthUnit::Meter, "m"}, - {LengthUnit::CentiMeter, "cm"}, - {LengthUnit::MilliMeter, "mm"}, - {LengthUnit::Yard, "yd"}, - {LengthUnit::Foot, "ft"}, - {LengthUnit::Inch, "in"}, -}) +//#include #endif diff --git a/server/src/enum/loconetcommandstation.hpp b/server/src/enum/loconetcommandstation.hpp index 0cd80461..90d4876f 100644 --- a/server/src/enum/loconetcommandstation.hpp +++ b/server/src/enum/loconetcommandstation.hpp @@ -31,23 +31,16 @@ inline constexpr std::array LocoNetCommandStationValues{{ LocoNetCommandStation::Custom, - LocoNetCommandStation::DigiKeijsDR5000, + LocoNetCommandStation::DigikeijsDR5000, LocoNetCommandStation::UhlenbrockIntellibox, }}; -NLOHMANN_JSON_SERIALIZE_ENUM(LocoNetCommandStation, -{ - {LocoNetCommandStation::Custom, "custom"}, - {LocoNetCommandStation::UhlenbrockIntellibox, "uhlenbrock_intellibox"}, - {LocoNetCommandStation::DigiKeijsDR5000, "digikeijs_dr5000"}, -}) - #ifndef DISABLE_LUA_SCRIPTING LUA_ENUM_VALUES(LocoNetCommandStation, 3, { {LocoNetCommandStation::Custom, "CUSTOM"}, {LocoNetCommandStation::UhlenbrockIntellibox, "UHLENBROCK_INTELLIBOX"}, - {LocoNetCommandStation::DigiKeijsDR5000, "DIGIKEIJS_DR5000"}, + {LocoNetCommandStation::DigikeijsDR5000, "DIGIKEIJS_DR5000"}, }) #endif diff --git a/server/src/enum/loconetserialinterface.hpp b/server/src/enum/loconetserialinterface.hpp index 5e37eaa9..a357af70 100644 --- a/server/src/enum/loconetserialinterface.hpp +++ b/server/src/enum/loconetserialinterface.hpp @@ -31,22 +31,15 @@ inline constexpr std::array LocoNetSerialInterfaceValues{{ LocoNetSerialInterface::Custom, - LocoNetSerialInterface::DigiKeijsDR5000, + LocoNetSerialInterface::DigikeijsDR5000, LocoNetSerialInterface::RoSoftLocoNetInterface, }}; -NLOHMANN_JSON_SERIALIZE_ENUM(LocoNetSerialInterface, -{ - {LocoNetSerialInterface::Custom, "custom"}, - {LocoNetSerialInterface::DigiKeijsDR5000, "digikeijs_dr5000"}, - {LocoNetSerialInterface::RoSoftLocoNetInterface, "rosoft_loconet_interface"}, -}) - #ifndef DISABLE_LUA_SCRIPTING LUA_ENUM_VALUES(LocoNetSerialInterface, 3, { {LocoNetSerialInterface::Custom, "CUSTOM"}, - {LocoNetSerialInterface::DigiKeijsDR5000, "DIGIKEIJS_DR5000"}, + {LocoNetSerialInterface::DigikeijsDR5000, "DIGIKEIJS_DR5000"}, {LocoNetSerialInterface::RoSoftLocoNetInterface, "ROSOFT_LOCONET_INTERFACE"}, }) #endif diff --git a/server/src/enum/serialflowcontrol.hpp b/server/src/enum/serialflowcontrol.hpp index 4fafcd3a..b52a7bd9 100644 --- a/server/src/enum/serialflowcontrol.hpp +++ b/server/src/enum/serialflowcontrol.hpp @@ -34,12 +34,6 @@ inline constexpr std::array SerialFlowControlValues{{ SerialFlowControl::Hardware, }}; -NLOHMANN_JSON_SERIALIZE_ENUM(SerialFlowControl, -{ - {SerialFlowControl::None, "none"}, - {SerialFlowControl::Hardware, "hardware"}, -}) - #ifndef DISABLE_LUA_SCRIPTING LUA_ENUM_VALUES(SerialFlowControl, 2, { diff --git a/server/src/enum/worldscale.hpp b/server/src/enum/worldscale.hpp new file mode 100644 index 00000000..6a274df8 --- /dev/null +++ b/server/src/enum/worldscale.hpp @@ -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 + +inline constexpr std::array WorldScaleValues{{ + WorldScale::H0, + WorldScale::N, + WorldScale::TT, + WorldScale::Z, + WorldScale::Custom, +}}; + +#endif diff --git a/server/src/enum/xpressnetcommandstation.hpp b/server/src/enum/xpressnetcommandstation.hpp index 0ec5ae9b..ba5350d7 100644 --- a/server/src/enum/xpressnetcommandstation.hpp +++ b/server/src/enum/xpressnetcommandstation.hpp @@ -24,18 +24,15 @@ #define TRAINTASTIC_SERVER_ENUM_XPRESSNETCOMMANDSTATION_HPP #include -#include #ifndef DISABLE_LUA_SCRIPTING #include "../lua/enumvalues.hpp" #endif -inline constexpr std::array XpressNetCommandStationValues{{XpressNetCommandStation::Custom, XpressNetCommandStation::Roco10764}}; - -NLOHMANN_JSON_SERIALIZE_ENUM(XpressNetCommandStation, -{ - {XpressNetCommandStation::Custom, "custom"}, - {XpressNetCommandStation::Roco10764, "roco_10764"}, -}) +inline constexpr std::array XpressNetCommandStationValues{{ + XpressNetCommandStation::Custom, + XpressNetCommandStation::Roco10764, + XpressNetCommandStation::DigikeijsDR5000, +}}; #ifndef DISABLE_LUA_SCRIPTING LUA_ENUM_VALUES(XpressNetCommandStation, 2, diff --git a/server/src/enum/xpressnetserialinterface.hpp b/server/src/enum/xpressnetserialinterface.hpp index 96e55e44..f0a6cd0c 100644 --- a/server/src/enum/xpressnetserialinterface.hpp +++ b/server/src/enum/xpressnetserialinterface.hpp @@ -24,7 +24,6 @@ #define TRAINTASTIC_SERVER_ENUM_XPRESSNETSERIALINTERFACE_HPP #include -#include inline constexpr std::array XpressNetSerialInterfaceValues{{ XpressNetSerialInterface::Custom, @@ -34,13 +33,4 @@ inline constexpr std::array XpressNetSerialInterfac XpressNetSerialInterface::RoSoftS88XPressNetLI, }}; -NLOHMANN_JSON_SERIALIZE_ENUM(XpressNetSerialInterface, -{ - {XpressNetSerialInterface::Custom, "custom"}, - {XpressNetSerialInterface::LenzLI100, "lenz_li100"}, - {XpressNetSerialInterface::LenzLI100F, "lenz_li100f"}, - {XpressNetSerialInterface::LenzLI101F, "lenz_li101f"}, - {XpressNetSerialInterface::RoSoftS88XPressNetLI, "rosoft_s88xpressnetli"}, -}) - #endif diff --git a/server/src/hardware/commandstation/commandstation.cpp b/server/src/hardware/commandstation/commandstation.cpp index 11bdb55b..66572458 100644 --- a/server/src/hardware/commandstation/commandstation.cpp +++ b/server/src/hardware/commandstation/commandstation.cpp @@ -27,6 +27,7 @@ #include "../../world/world.hpp" #include "../decoder/decoder.hpp" #include "../decoder/decoderlist.hpp" +#include "../../core/attributes.hpp" CommandStation::CommandStation(const std::weak_ptr& world, std::string_view _id) : IdObject(world, _id), @@ -59,17 +60,21 @@ CommandStation::CommandStation(const std::weak_ptr& world, std::string_vi auto w = world.lock(); const bool editable = w && contains(w->state.value(), WorldState::Edit); - m_interfaceItems.add(name) - .addAttributeEnabled(editable); + Attributes::addEnabled(name, editable); + m_interfaceItems.add(name); + m_interfaceItems.add(online); - m_interfaceItems.insertBefore(emergencyStop, notes) - .addAttributeEnabled(editable) - .addAttributeObjectEditor(false); - m_interfaceItems.insertBefore(trackVoltageOff, notes) - .addAttributeEnabled(editable) - .addAttributeObjectEditor(false); + + Attributes::addObjectEditor(emergencyStop, false); + m_interfaceItems.insertBefore(emergencyStop, notes); + + Attributes::addObjectEditor(trackVoltageOff, false); + m_interfaceItems.insertBefore(trackVoltageOff, notes); + m_interfaceItems.add(decoders); + m_interfaceItems.add(controllers); + m_interfaceItems.add(notes); } diff --git a/server/src/hardware/commandstation/commandstationlist.cpp b/server/src/hardware/commandstation/commandstationlist.cpp index f5bd59b6..d77396a3 100644 --- a/server/src/hardware/commandstation/commandstationlist.cpp +++ b/server/src/hardware/commandstation/commandstationlist.cpp @@ -25,6 +25,7 @@ #include "commandstations.hpp" #include "../../world/world.hpp" #include "../../world/getworld.hpp" +#include "../../core/attributes.hpp" CommandStationList::CommandStationList(Object& _parent, const std::string& parentPropertyName) : ObjectList(_parent, parentPropertyName), @@ -47,11 +48,12 @@ CommandStationList::CommandStationList(Object& _parent, const std::string& paren auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); - m_interfaceItems.add(add) - .addAttributeEnabled(editable); - m_interfaceItems.add(remove) - .addAttributeEnabled(editable); - } + Attributes::addEnabled(add, editable); + m_interfaceItems.add(add); + + Attributes::addEnabled(remove, editable); + m_interfaceItems.add(remove); +} TableModelPtr CommandStationList::getModel() { diff --git a/server/src/hardware/commandstation/commandstations.hpp b/server/src/hardware/commandstation/commandstations.hpp index d121af67..72ef6e63 100644 --- a/server/src/hardware/commandstation/commandstations.hpp +++ b/server/src/hardware/commandstation/commandstations.hpp @@ -20,8 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_CREATE_HPP -#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_CREATE_HPP +#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_COMMANDSTATIONS_HPP +#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_COMMANDSTATIONS_HPP #include "commandstation.hpp" diff --git a/server/src/hardware/commandstation/loconetserial.cpp b/server/src/hardware/commandstation/loconetserial.cpp index 4929a92b..68a05052 100644 --- a/server/src/hardware/commandstation/loconetserial.cpp +++ b/server/src/hardware/commandstation/loconetserial.cpp @@ -21,9 +21,9 @@ */ #include "loconetserial.hpp" -//#include "../../world/world.hpp" #include "../../core/traintastic.hpp" #include "../../core/eventloop.hpp" +#include "../../core/attributes.hpp" LocoNetSerial::LocoNetSerial(const std::weak_ptr& world, std::string_view _id) : SerialCommandStation(world, _id), @@ -35,7 +35,7 @@ LocoNetSerial::LocoNetSerial(const std::weak_ptr& world, std::string_view case LocoNetSerialInterface::Custom: break; - case LocoNetSerialInterface::DigiKeijsDR5000: + case LocoNetSerialInterface::DigikeijsDR5000: baudrate = 115200; flowControl = SerialFlowControl::Hardware; break; @@ -51,31 +51,11 @@ LocoNetSerial::LocoNetSerial(const std::weak_ptr& world, std::string_view name = "LocoNet (serial)"; loconet.setValueInternal(std::make_shared(*this, loconet.name(), std::bind(&LocoNetSerial::send, this, std::placeholders::_1))); - interface.addAttributeEnabled(!online); - + Attributes::addEnabled(interface, !online); + Attributes::addValues(interface, LocoNetSerialInterfaceValues); m_interfaceItems.insertBefore(interface, baudrate); m_interfaceItems.insertBefore(loconet, notes); } -/* -bool LocoNetSerial::setOnline(bool& value) -{ - if(!m_serialPort.is_open() && value) - { - if(!start()) - { - value = false; - return false; - } - m_readBufferOffset = 0; - read(); - - loconet->queryLocoSlots(); - } - else if(m_serialPort.is_open() && !value) - stop(); - - return true; -}*/ void LocoNetSerial::emergencyStopChanged(bool value) { @@ -115,6 +95,11 @@ bool LocoNetSerial::send(const LocoNet::Message& message) return true; } +void LocoNetSerial::started() +{ + loconet->queryLocoSlots(); +} + void LocoNetSerial::read() { m_serialPort.async_read_some(boost::asio::buffer(m_readBuffer.data() + m_readBufferOffset, m_readBuffer.size() - m_readBufferOffset), diff --git a/server/src/hardware/commandstation/loconetserial.hpp b/server/src/hardware/commandstation/loconetserial.hpp index f8939aae..c30cb0a2 100644 --- a/server/src/hardware/commandstation/loconetserial.hpp +++ b/server/src/hardware/commandstation/loconetserial.hpp @@ -26,8 +26,6 @@ #include "serialcommandstation.hpp" #include "../protocol/loconet/loconet.hpp" #include "../../enum/loconetserialinterface.hpp" -//#include "../../enum/serialflowcontrol.hpp" -//#include class LocoNetSerial : public SerialCommandStation { @@ -39,6 +37,7 @@ class LocoNetSerial : public SerialCommandStation bool start(); void stop(); bool send(const LocoNet::Message& msg); + void started() final; void read() final; public: diff --git a/server/src/hardware/commandstation/protocol/xpressnet.cpp b/server/src/hardware/commandstation/protocol/xpressnet.cpp deleted file mode 100644 index 6ee247d9..00000000 --- a/server/src/hardware/commandstation/protocol/xpressnet.cpp +++ /dev/null @@ -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 - * - * 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, const std::string& id, std::function&& 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(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& 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& 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& 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& 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& 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& 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& 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& 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& f = decoder.getFunction(i); - if(f && f->value) - cmd.state |= 1 << (i - 13); - } - - cmd.checksum = calcChecksum(&cmd); - - m_send(&cmd); -} - -} -#endif diff --git a/server/src/hardware/commandstation/protocol/xpressnet.hpp b/server/src/hardware/commandstation/protocol/xpressnet.hpp deleted file mode 100644 index 11eef0b3..00000000 --- a/server/src/hardware/commandstation/protocol/xpressnet.hpp +++ /dev/null @@ -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 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 commandStation; - Property useFunctionStateCommands; - Property useRocoF13F20Command; - - XpressNet(const std::weak_ptr& world, const std::string& id, std::function&& send); - - bool isDecoderSupported(const Decoder& decoder) const; - - void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber); -}; - -} } - -#endif diff --git a/server/src/hardware/commandstation/rocoz21.cpp b/server/src/hardware/commandstation/rocoz21.cpp index 532a8e1a..35f5987a 100644 --- a/server/src/hardware/commandstation/rocoz21.cpp +++ b/server/src/hardware/commandstation/rocoz21.cpp @@ -24,6 +24,7 @@ #include "../../core/traintastic.hpp" #include "../../world/world.hpp" #include "../../core/eventloop.hpp" +#include "../../core/attributes.hpp" #include "../decoder/decoderchangeflags.hpp" #include "../protocol/xpressnet/messages.hpp" #include "../protocol/z21.hpp" @@ -87,41 +88,41 @@ RocoZ21::RocoZ21(const std::weak_ptr& world, std::string_view _id) : return false; })); - m_interfaceItems.insertBefore(hostname, notes) - .addAttributeEnabled(true); - m_interfaceItems.insertBefore(port, notes) - .addAttributeEnabled(true); + Attributes::addEnabled(hostname, true); + m_interfaceItems.insertBefore(hostname, notes); + Attributes::addEnabled(port, true); + m_interfaceItems.insertBefore(port, notes); m_interfaceItems.insertBefore(loconet, notes); - m_interfaceItems.insertBefore(serialNumber, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(hardwareType, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(firmwareVersion, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(mainCurrent, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(progCurrent, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(filteredMainCurrent, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(temperature, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(supplyVoltage, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(vccVoltage, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(shortCircuit, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(programmingModeActive, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(highTemperature, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(powerLost, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(shortCircutInternal, notes) - .addAttributeCategory(Category::Info); - m_interfaceItems.insertBefore(shortCircutExternal, notes) - .addAttributeCategory(Category::Info); + Attributes::addCategory(serialNumber, Category::Info); + m_interfaceItems.insertBefore(serialNumber, notes); + Attributes::addCategory(hardwareType, Category::Info); + m_interfaceItems.insertBefore(hardwareType, notes); + Attributes::addCategory(firmwareVersion, Category::Info); + m_interfaceItems.insertBefore(firmwareVersion, notes); + Attributes::addCategory(mainCurrent, Category::Info); + m_interfaceItems.insertBefore(mainCurrent, notes); + Attributes::addCategory(progCurrent, Category::Info); + m_interfaceItems.insertBefore(progCurrent, notes); + Attributes::addCategory(filteredMainCurrent, Category::Info); + m_interfaceItems.insertBefore(filteredMainCurrent, notes); + Attributes::addCategory(temperature, Category::Info); + m_interfaceItems.insertBefore(temperature, notes); + Attributes::addCategory(firmwareVersion, Category::Info); + m_interfaceItems.insertBefore(supplyVoltage, notes); + Attributes::addCategory(vccVoltage, Category::Info); + m_interfaceItems.insertBefore(vccVoltage, notes); + Attributes::addCategory(firmwareVersion, Category::Info); + m_interfaceItems.insertBefore(shortCircuit, notes); + Attributes::addCategory(programmingModeActive, Category::Info); + m_interfaceItems.insertBefore(programmingModeActive, notes); + Attributes::addCategory(highTemperature, Category::Info); + m_interfaceItems.insertBefore(highTemperature, notes); + Attributes::addCategory(powerLost, Category::Info); + m_interfaceItems.insertBefore(powerLost, notes); + Attributes::addCategory(shortCircutInternal, Category::Info); + m_interfaceItems.insertBefore(shortCircutInternal, notes); + Attributes::addCategory(shortCircutExternal, Category::Info); + m_interfaceItems.insertBefore(shortCircutExternal, notes); } void RocoZ21::emergencyStopChanged(bool value) diff --git a/server/src/hardware/commandstation/rocoz21.hpp b/server/src/hardware/commandstation/rocoz21.hpp index d8e1dfcf..190a69e8 100644 --- a/server/src/hardware/commandstation/rocoz21.hpp +++ b/server/src/hardware/commandstation/rocoz21.hpp @@ -20,8 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_Z21_HPP -#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_Z21_HPP +#ifndef TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_ROCOZ21_HPP +#define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_ROCOZ21_HPP #include "commandstation.hpp" #include diff --git a/server/src/hardware/commandstation/serialcommandstation.cpp b/server/src/hardware/commandstation/serialcommandstation.cpp index fdcca803..4ebefc1f 100644 --- a/server/src/hardware/commandstation/serialcommandstation.cpp +++ b/server/src/hardware/commandstation/serialcommandstation.cpp @@ -23,6 +23,7 @@ #include "serialcommandstation.hpp" #include "../../core/traintastic.hpp" #include "../../core/eventloop.hpp" +#include "../../core/attributes.hpp" SerialCommandStation::SerialCommandStation(const std::weak_ptr& world, std::string_view _id) : CommandStation(world, _id), @@ -40,12 +41,12 @@ SerialCommandStation::SerialCommandStation(const std::weak_ptr& world, st //interface = LocoNetSerialInterface::Custom; }} { - port.addAttributeEnabled(!online); - baudrate.addAttributeEnabled(!online); - flowControl.addAttributeEnabled(!online); - + Attributes::addEnabled(port, !online); m_interfaceItems.insertBefore(port, notes); + Attributes::addEnabled(baudrate, !online); m_interfaceItems.insertBefore(baudrate, notes); + Attributes::addEnabled(flowControl, !online); + Attributes::addValues(flowControl, SerialFlowControlValues); m_interfaceItems.insertBefore(flowControl, notes); } @@ -60,8 +61,6 @@ bool SerialCommandStation::setOnline(bool& value) } m_readBufferOffset = 0; read(); - - //loconet->queryLocoSlots(); } else if(m_serialPort.is_open() && !value) stop(); diff --git a/server/src/hardware/commandstation/serialcommandstation.hpp b/server/src/hardware/commandstation/serialcommandstation.hpp index 80a936ac..5892fe76 100644 --- a/server/src/hardware/commandstation/serialcommandstation.hpp +++ b/server/src/hardware/commandstation/serialcommandstation.hpp @@ -38,6 +38,8 @@ class SerialCommandStation : public CommandStation bool start(); void stop(); + + virtual void started() {} virtual void read() = 0; public: diff --git a/server/src/hardware/commandstation/xpressnet/xpressnet.cpp b/server/src/hardware/commandstation/xpressnet/xpressnet.cpp deleted file mode 100644 index 405a0de2..00000000 --- a/server/src/hardware/commandstation/xpressnet/xpressnet.cpp +++ /dev/null @@ -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, 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; -} - -} diff --git a/server/src/hardware/commandstation/xpressnet/xpressnet.hpp b/server/src/hardware/commandstation/xpressnet/xpressnet.hpp deleted file mode 100644 index 76511b85..00000000 --- a/server/src/hardware/commandstation/xpressnet/xpressnet.hpp +++ /dev/null @@ -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 commandStation; - Property useEmergencyStopLocomotiveCommand; - Property useFunctionStateCommands; - Property useRocoF13F20Command; - - XpressNet(const std::weak_ptr& world, std::string_view _id); -}; - -} - -#endif diff --git a/server/src/hardware/commandstation/xpressnetserial.cpp b/server/src/hardware/commandstation/xpressnetserial.cpp index 77d90b59..9fcea6ae 100644 --- a/server/src/hardware/commandstation/xpressnetserial.cpp +++ b/server/src/hardware/commandstation/xpressnetserial.cpp @@ -24,6 +24,7 @@ #include "../../world/world.hpp" #include "../../core/traintastic.hpp" #include "../../core/eventloop.hpp" +#include "../../core/attributes.hpp" XpressNetSerial::XpressNetSerial(const std::weak_ptr& world, std::string_view _id) : SerialCommandStation(world, _id), @@ -57,6 +58,7 @@ XpressNetSerial::XpressNetSerial(const std::weak_ptr& world, std::string_ name = "XpressNet (serial)"; xpressnet.setValueInternal(std::make_shared(*this, xpressnet.name(), std::bind(&XpressNetSerial::send, this, std::placeholders::_1))); + Attributes::addValues(interface, XpressNetSerialInterfaceValues); m_interfaceItems.insertBefore(interface, baudrate); m_interfaceItems.insertBefore(xpressnet, notes); } diff --git a/server/src/hardware/controller/controller.cpp b/server/src/hardware/controller/controller.cpp index fbb78738..67c9a71a 100644 --- a/server/src/hardware/controller/controller.cpp +++ b/server/src/hardware/controller/controller.cpp @@ -25,6 +25,7 @@ #include "controllerlisttablemodel.hpp" #include "../commandstation/commandstation.hpp" #include "../../world/getworld.hpp" +#include "../../core/attributes.hpp" Controller::Controller(const std::weak_ptr& _world, std::string_view _id) : IdObject(_world, _id), @@ -51,8 +52,8 @@ Controller::Controller(const std::weak_ptr& _world, std::string_view _id) const bool editable = world && contains(world->state.value(), WorldState::Edit); m_interfaceItems.add(name); - m_interfaceItems.add(commandStation) - .addAttributeEnabled(editable); + Attributes::addEnabled(commandStation, editable); + m_interfaceItems.add(commandStation); m_interfaceItems.add(active); m_interfaceItems.add(notes); } diff --git a/server/src/hardware/controller/controllerlist.cpp b/server/src/hardware/controller/controllerlist.cpp index 1199017c..94f84593 100644 --- a/server/src/hardware/controller/controllerlist.cpp +++ b/server/src/hardware/controller/controllerlist.cpp @@ -25,6 +25,7 @@ #include "controllers.hpp" #include "../commandstation/commandstation.hpp" #include "../../world/getworld.hpp" +#include "../../core/attributes.hpp" ControllerList::ControllerList(Object& _parent, const std::string& parentPropertyName) : ObjectList(_parent, parentPropertyName), @@ -45,8 +46,8 @@ ControllerList::ControllerList(Object& _parent, const std::string& parentPropert auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); - m_interfaceItems.add(add) - .addAttributeEnabled(editable); + Attributes::addEnabled(add, editable); + m_interfaceItems.add(add); } TableModelPtr ControllerList::getModel() diff --git a/server/src/hardware/controller/wlanmaus.cpp b/server/src/hardware/controller/wlanmaus.cpp index 39a2d43b..aa38f64e 100644 --- a/server/src/hardware/controller/wlanmaus.cpp +++ b/server/src/hardware/controller/wlanmaus.cpp @@ -27,6 +27,7 @@ #include "../decoder/decoder.hpp" #include "../protocol/z21.hpp" #include "../../utils/to_hex.hpp" +#include "../../core/attributes.hpp" WLANmaus::WLANmaus(const std::weak_ptr world, std::string_view _id) : Controller(world, _id), @@ -34,8 +35,8 @@ WLANmaus::WLANmaus(const std::weak_ptr world, std::string_view _id) : m_blockLocoInfo{nullptr}, port{this, "port", 21105, PropertyFlags::ReadWrite | PropertyFlags::Store} { - m_interfaceItems.add(port) - .addAttributeEnabled(!active); + Attributes::addEnabled(port, !active); + m_interfaceItems.add(port); } bool WLANmaus::setActive(bool& value) diff --git a/server/src/hardware/decoder/decoder.cpp b/server/src/hardware/decoder/decoder.cpp index cd59800b..34b57b0b 100644 --- a/server/src/hardware/decoder/decoder.cpp +++ b/server/src/hardware/decoder/decoder.cpp @@ -28,6 +28,7 @@ #include "decoderfunctionlist.hpp" #include "../../world/world.hpp" #include "../commandstation/commandstation.hpp" +#include "../../core/attributes.hpp" //constexpr uint16_t addressDCCMin = 1; constexpr uint16_t addressDCCShortMax = 127; @@ -103,20 +104,22 @@ Decoder::Decoder(const std::weak_ptr& world, std::string_view _id) : //auto w = world.lock(); // const bool editable = w && contains(w->state.value(), WorldState::Edit) && speedStep == 0; - m_interfaceItems.add(name) - .addAttributeEnabled(false); - m_interfaceItems.add(commandStation) - .addAttributeEnabled(false); - m_interfaceItems.add(protocol) - .addAttributeEnabled(false); - m_interfaceItems.add(address) - .addAttributeEnabled(false); - m_interfaceItems.add(longAddress) - .addAttributeEnabled(false); + Attributes::addEnabled(name, false); + m_interfaceItems.add(name); + Attributes::addEnabled(commandStation, false); + m_interfaceItems.add(commandStation); + Attributes::addEnabled(protocol, false); + Attributes::addValues(protocol, DecoderProtocolValues); + m_interfaceItems.add(protocol); + Attributes::addEnabled(address, false); + m_interfaceItems.add(address); + Attributes::addEnabled(longAddress, false); + m_interfaceItems.add(longAddress); m_interfaceItems.add(emergencyStop); + Attributes::addValues(direction, DirectionValues); m_interfaceItems.add(direction); - m_interfaceItems.add(speedSteps) - .addAttributeEnabled(false); + Attributes::addEnabled(speedSteps, false); + m_interfaceItems.add(speedSteps); m_interfaceItems.add(speedStep); m_interfaceItems.add(functions); m_interfaceItems.add(notes); diff --git a/server/src/hardware/decoder/decoderfunction.cpp b/server/src/hardware/decoder/decoderfunction.cpp index a241ab3c..43e0f7c0 100644 --- a/server/src/hardware/decoder/decoderfunction.cpp +++ b/server/src/hardware/decoder/decoderfunction.cpp @@ -22,6 +22,7 @@ #include "decoder.hpp" #include "decoderchangeflags.hpp" #include "../../world/world.hpp" +#include "../../core/attributes.hpp" const std::shared_ptr DecoderFunction::null; @@ -41,10 +42,10 @@ DecoderFunction::DecoderFunction(Decoder& decoder, std::string_view _id) : auto w = decoder.world().lock(); const bool editable = w && contains(w->state.value(), WorldState::Edit); - m_interfaceItems.add(number) - .addAttributeEnabled(editable); - m_interfaceItems.add(name) - .addAttributeEnabled(editable); + Attributes::addEnabled(number, editable); + m_interfaceItems.add(number); + Attributes::addEnabled(name, editable); + m_interfaceItems.add(name); } void DecoderFunction::worldEvent(WorldState state, WorldEvent event) diff --git a/server/src/hardware/decoder/decoderfunctionlist.cpp b/server/src/hardware/decoder/decoderfunctionlist.cpp index a1791454..e416f6bc 100644 --- a/server/src/hardware/decoder/decoderfunctionlist.cpp +++ b/server/src/hardware/decoder/decoderfunctionlist.cpp @@ -24,6 +24,7 @@ #include "decoderfunctionlisttablemodel.hpp" #include "decoder.hpp" #include "../../world/getworld.hpp" +#include "../../core/attributes.hpp" DecoderFunctionList::DecoderFunctionList(Object& _parent, const std::string& parentPropertyName) : ObjectList(_parent, parentPropertyName), @@ -57,8 +58,8 @@ DecoderFunctionList::DecoderFunctionList(Object& _parent, const std::string& par auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); - m_interfaceItems.add(add) - .addAttributeEnabled(editable); + Attributes::addEnabled(add, editable); + m_interfaceItems.add(add); } TableModelPtr DecoderFunctionList::getModel() diff --git a/server/src/hardware/decoder/decoderlist.cpp b/server/src/hardware/decoder/decoderlist.cpp index 07c531a6..cc685587 100644 --- a/server/src/hardware/decoder/decoderlist.cpp +++ b/server/src/hardware/decoder/decoderlist.cpp @@ -24,6 +24,7 @@ #include "decoderlisttablemodel.hpp" #include "../commandstation/commandstation.hpp" #include "../../world/getworld.hpp" +#include "../../core/attributes.hpp" DecoderList::DecoderList(Object& _parent, const std::string& parentPropertyName) : ObjectList(_parent, parentPropertyName), @@ -45,8 +46,8 @@ DecoderList::DecoderList(Object& _parent, const std::string& parentPropertyName) auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); - m_interfaceItems.add(add) - .addAttributeEnabled(editable); + Attributes::addEnabled(add, editable); + m_interfaceItems.add(add); } TableModelPtr DecoderList::getModel() diff --git a/server/src/hardware/input/loconetinput.cpp b/server/src/hardware/input/loconetinput.cpp index 1b1adfff..c722c221 100644 --- a/server/src/hardware/input/loconetinput.cpp +++ b/server/src/hardware/input/loconetinput.cpp @@ -21,6 +21,7 @@ */ #include "loconetinput.hpp" +#include "../../core/attributes.hpp" LocoNetInput::LocoNetInput(const std::weak_ptr world, std::string_view _id) : Input(world, _id), @@ -44,10 +45,10 @@ LocoNetInput::LocoNetInput(const std::weak_ptr world, std::string_view _i return false; }} { - m_interfaceItems.add(loconet) - .addAttributeEnabled(false); - m_interfaceItems.add(address) - .addAttributeEnabled(false); + Attributes::addEnabled(loconet, false); + m_interfaceItems.add(loconet); + Attributes::addEnabled(address, false); + m_interfaceItems.add(address); } void LocoNetInput::worldEvent(WorldState state, WorldEvent event) diff --git a/server/src/hardware/protocol/loconet/loconet.cpp b/server/src/hardware/protocol/loconet/loconet.cpp index 9349c951..aa40b3ee 100644 --- a/server/src/hardware/protocol/loconet/loconet.cpp +++ b/server/src/hardware/protocol/loconet/loconet.cpp @@ -27,6 +27,7 @@ #include "../../../core/traintastic.hpp" #include "../../commandstation/commandstation.hpp" #include "../../input/loconetinput.hpp" +#include "../../../core/attributes.hpp" namespace LocoNet { @@ -44,9 +45,9 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu SubObject(_parent, parentPropertyName), m_commandStation{dynamic_cast(&_parent)}, m_send{std::move(send)}, - m_debugLog{true/*false*/}, + m_debugLog{false}, m_queryLocoSlots{SLOT_UNKNOWN}, - commandStation{this, "command_station", LocoNetCommandStation::Custom, PropertyFlags::ReadWrite, + commandStation{this, "command_station", LocoNetCommandStation::Custom, PropertyFlags::ReadWrite | PropertyFlags::Store, [this](LocoNetCommandStation value) { switch(value) @@ -54,7 +55,7 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu case LocoNetCommandStation::Custom: break; - case LocoNetCommandStation::DigiKeijsDR5000: + case LocoNetCommandStation::DigikeijsDR5000: break; case LocoNetCommandStation::UhlenbrockIntellibox: @@ -69,8 +70,9 @@ LocoNet::LocoNet(Object& _parent, const std::string& parentPropertyName, std::fu { assert(m_send); - m_interfaceItems.add(commandStation) - .addAttributeEnabled(false); + Attributes::addEnabled(commandStation, m_commandStation && !m_commandStation->online); + Attributes::addValues(commandStation, LocoNetCommandStationValues); + m_interfaceItems.add(commandStation); m_interfaceItems.add(debugLog); } diff --git a/server/src/hardware/protocol/xpressnet/xpressnet.cpp b/server/src/hardware/protocol/xpressnet/xpressnet.cpp index b39b3f35..dbdc713a 100644 --- a/server/src/hardware/protocol/xpressnet/xpressnet.cpp +++ b/server/src/hardware/protocol/xpressnet/xpressnet.cpp @@ -24,6 +24,7 @@ #include "../../../core/traintastic.hpp" #include "../../../core/eventloop.hpp" #include "../../decoder/decoder.hpp" +#include "../../../core/attributes.hpp" namespace XpressNet { @@ -42,21 +43,28 @@ XpressNet::XpressNet(Object& _parent, const std::string& parentPropertyName, std case XpressNetCommandStation::Roco10764: useEmergencyStopLocomotiveCommand.setValueInternal(false); - useFunctionStateCommands.setValueInternal(false); + //useFunctionStateCommands.setValueInternal(false); + useRocoF13F20Command.setValueInternal(true); + break; + + case XpressNetCommandStation::DigikeijsDR5000: + useEmergencyStopLocomotiveCommand.setValueInternal(false); // ????? + //useFunctionStateCommands.setValueInternal(false); useRocoF13F20Command.setValueInternal(true); break; } + // TODO: updateEnabled(); }}, useEmergencyStopLocomotiveCommand{this, "use_emergency_stop_locomotive_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store, [this](bool) { commandStation = XpressNetCommandStation::Custom; }}, - useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite | PropertyFlags::Store, - [this](bool) - { - commandStation = XpressNetCommandStation::Custom; - }}, + //useFunctionStateCommands{this, "use_function_state_commands", false, PropertyFlags::ReadWrite | PropertyFlags::Store, + // [this](bool) + // { + // commandStation = XpressNetCommandStation::Custom; + // }}, useRocoF13F20Command{this, "use_roco_f13_f20_command", false, PropertyFlags::ReadWrite | PropertyFlags::Store, [this](bool) { @@ -68,14 +76,15 @@ XpressNet::XpressNet(Object& _parent, const std::string& parentPropertyName, std m_debugLog = value; }} { - m_interfaceItems.add(commandStation) - .addAttributeEnabled(false); - m_interfaceItems.add(useEmergencyStopLocomotiveCommand) - .addAttributeEnabled(false); - m_interfaceItems.add(useFunctionStateCommands) - .addAttributeEnabled(false); - m_interfaceItems.add(useRocoF13F20Command) - .addAttributeEnabled(false); + Attributes::addEnabled(commandStation, false); + Attributes::addValues(commandStation, XpressNetCommandStationValues); + m_interfaceItems.add(commandStation); + Attributes::addEnabled(useEmergencyStopLocomotiveCommand, false); + m_interfaceItems.add(useEmergencyStopLocomotiveCommand); + //Attributes::addEnabled(useFunctionStateCommands, false); + //m_interfaceItems.add(useFunctionStateCommands); + Attributes::addEnabled(useRocoF13F20Command, false); + m_interfaceItems.add(useRocoF13F20Command); } void XpressNet::worldEvent(WorldState state, WorldEvent event) @@ -86,7 +95,7 @@ void XpressNet::worldEvent(WorldState state, WorldEvent event) commandStation.setAttributeEnabled(editable); useEmergencyStopLocomotiveCommand.setAttributeEnabled(editable); - useFunctionStateCommands.setAttributeEnabled(editable); + //useFunctionStateCommands.setAttributeEnabled(editable); useRocoF13F20Command.setAttributeEnabled(editable); } diff --git a/server/src/hardware/protocol/xpressnet/xpressnet.hpp b/server/src/hardware/protocol/xpressnet/xpressnet.hpp index ec1d3385..dc7cf551 100644 --- a/server/src/hardware/protocol/xpressnet/xpressnet.hpp +++ b/server/src/hardware/protocol/xpressnet/xpressnet.hpp @@ -50,7 +50,7 @@ class XpressNet : public SubObject Property commandStation; Property useEmergencyStopLocomotiveCommand; - Property useFunctionStateCommands; + //Property useFunctionStateCommands; Property useRocoF13F20Command; Property debugLog; diff --git a/server/src/lua/script.cpp b/server/src/lua/script.cpp index aeb95989..5642a827 100644 --- a/server/src/lua/script.cpp +++ b/server/src/lua/script.cpp @@ -27,6 +27,7 @@ #include "../world/world.hpp" #include "../enum/worldevent.hpp" #include "../set/worldstate.hpp" +#include "../core/attributes.hpp" namespace Lua { @@ -49,8 +50,8 @@ Script::Script(const std::weak_ptr& world, std::string_view _id) : m_interfaceItems.add(name); m_interfaceItems.add(active); - m_interfaceItems.add(code) - .addAttributeEnabled(!active && editable); + Attributes::addEnabled(code, !active && editable); + m_interfaceItems.add(code); } void Script::addToWorld() diff --git a/server/src/lua/scriptlist.cpp b/server/src/lua/scriptlist.cpp index 0bca9d16..c3d83c77 100644 --- a/server/src/lua/scriptlist.cpp +++ b/server/src/lua/scriptlist.cpp @@ -23,6 +23,7 @@ #include "scriptlist.hpp" #include "scriptlisttablemodel.hpp" #include "../world/getworld.hpp" +#include "../core/attributes.hpp" namespace Lua { @@ -42,8 +43,8 @@ ScriptList::ScriptList(Object& _parent, const std::string& parentPropertyName) : auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); - m_interfaceItems.add(add) - .addAttributeEnabled(editable); + Attributes::addEnabled(add, editable); + m_interfaceItems.add(add); } TableModelPtr ScriptList::getModel() diff --git a/server/src/train/train.cpp b/server/src/train/train.cpp index 6f62c675..dfb4f65b 100644 --- a/server/src/train/train.cpp +++ b/server/src/train/train.cpp @@ -23,6 +23,7 @@ #include "train.hpp" #include "../world/world.hpp" #include "trainlisttablemodel.hpp" +#include "../core/attributes.hpp" Train::Train(const std::weak_ptr& world, std::string_view _id) : IdObject(world, _id), @@ -37,13 +38,14 @@ Train::Train(const std::weak_ptr& world, std::string_view _id) : auto w = world.lock(); const bool editable = w && contains(w->state.value(), WorldState::Edit); - m_interfaceItems.add(name) - .addAttributeEnabled(editable); + Attributes::addEnabled(name, editable); + m_interfaceItems.add(name); m_interfaceItems.add(lob); + Attributes::addValues(direction, DirectionValues); m_interfaceItems.add(direction); m_interfaceItems.add(speed); - m_interfaceItems.add(speedMax) - .addAttributeEnabled(editable); + Attributes::addEnabled(speedMax, editable); + m_interfaceItems.add(speedMax); m_interfaceItems.add(throttleSpeed); m_interfaceItems.add(weight); } diff --git a/server/src/train/trainlist.cpp b/server/src/train/trainlist.cpp index 32de8491..4cf8ba7a 100644 --- a/server/src/train/trainlist.cpp +++ b/server/src/train/trainlist.cpp @@ -24,6 +24,7 @@ #include "trainlisttablemodel.hpp" #include "../world/world.hpp" #include "../world/getworld.hpp" +#include "../core/attributes.hpp" TrainList::TrainList(Object& _parent, const std::string& parentPropertyName) : ObjectList(_parent, parentPropertyName), @@ -39,8 +40,8 @@ TrainList::TrainList(Object& _parent, const std::string& parentPropertyName) : auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); - m_interfaceItems.add(add) - .addAttributeEnabled(editable); + Attributes::addEnabled(add, editable); + m_interfaceItems.add(add); } TableModelPtr TrainList::getModel() diff --git a/server/src/utils/json.hpp b/server/src/utils/json.hpp new file mode 100644 index 00000000..c9d82e95 --- /dev/null +++ b/server/src/utils/json.hpp @@ -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 +#include +#include + +template +inline void to_json(const BasicJsonType& j, const EnumType& e, typename std::enable_if_t && !is_set_v>* = nullptr) +{ + e = EnumValues::value.at(e); +} + +template +inline void from_json(const BasicJsonType& j, EnumType& e, typename std::enable_if_t && !is_set_v>* = nullptr) +{ + auto it = std::find_if(EnumValues::value.cbegin(), EnumValues::value.cend(), + [j](const auto& v) + { + return v.second == j; + }); + + e = it != EnumValues::value.cend() ? it->first : EnumValues::value.cbegin()->first; +} + +template +inline void to_json(const BasicJsonType& j, const EnumType& e, typename std::enable_if_t>* = nullptr) +{ + assert(false); +} + +template +inline void from_json(const BasicJsonType& j, EnumType& e, typename std::enable_if_t>* = nullptr) +{ + assert(false); +} + +#endif diff --git a/server/src/vehicle/rail/railvehiclelist.cpp b/server/src/vehicle/rail/railvehiclelist.cpp index e398629f..25dc707f 100644 --- a/server/src/vehicle/rail/railvehiclelist.cpp +++ b/server/src/vehicle/rail/railvehiclelist.cpp @@ -23,8 +23,8 @@ #include "railvehiclelist.hpp" #include "railvehiclelisttablemodel.hpp" #include "railvehicles.hpp" -#include "../../world/world.hpp" #include "../../world/getworld.hpp" +#include "../../core/attributes.hpp" RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPropertyName) : ObjectList(_parent, parentPropertyName), @@ -40,8 +40,8 @@ RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPrope auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); - m_interfaceItems.add(add) - .addAttributeEnabled(editable); + Attributes::addEnabled(add, editable); + m_interfaceItems.add(add); } TableModelPtr RailVehicleList::getModel() diff --git a/server/src/vehicle/vehicle.cpp b/server/src/vehicle/vehicle.cpp index ff363ac0..0bc7070a 100644 --- a/server/src/vehicle/vehicle.cpp +++ b/server/src/vehicle/vehicle.cpp @@ -22,6 +22,7 @@ #include "vehicle.hpp" #include "../world/world.hpp" +#include "../core/attributes.hpp" Vehicle::Vehicle(const std::weak_ptr& world, std::string_view _id) : IdObject(world, _id), @@ -30,8 +31,8 @@ Vehicle::Vehicle(const std::weak_ptr& world, std::string_view _id) : auto w = world.lock(); const bool editable = w && contains(w->state.value(), WorldState::Edit); - m_interfaceItems.add(name) - .addAttributeEnabled(editable); + Attributes::addEnabled(name, editable); + m_interfaceItems.add(name); } void Vehicle::worldEvent(WorldState state, WorldEvent event) diff --git a/server/src/world/world.cpp b/server/src/world/world.cpp index 55e1935c..85328f03 100644 --- a/server/src/world/world.cpp +++ b/server/src/world/world.cpp @@ -28,6 +28,7 @@ #include "worldsaver.hpp" #include "../core/traintastic.hpp" #include "../core/objectlisttablemodel.hpp" +#include "../core/attributes.hpp" using nlohmann::json; @@ -121,6 +122,7 @@ World::World(Private) : m_filename = Traintastic::instance->worldDir() / to_string(m_uuid) / filename; m_interfaceItems.add(name); + Attributes::addValues(scale, WorldScaleValues); m_interfaceItems.add(scale); m_interfaceItems.add(commandStations); diff --git a/server/src/world/world.hpp b/server/src/world/world.hpp index 112e5ac9..fbe4c57b 100644 --- a/server/src/world/world.hpp +++ b/server/src/world/world.hpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include "../enum/worldscale.hpp" #include #include "../clock/clock.hpp" #include "../hardware/commandstation/commandstationlist.hpp" diff --git a/shared/src/traintastic/enum/attributetype.hpp b/shared/src/traintastic/enum/attributetype.hpp new file mode 100644 index 00000000..5a8c96d7 --- /dev/null +++ b/shared/src/traintastic/enum/attributetype.hpp @@ -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 + +enum class AttributeType : uint8_t +{ + Value = 1, + Values = 2, +}; + +#endif diff --git a/shared/src/traintastic/enum/commandstationstatus.hpp b/shared/src/traintastic/enum/commandstationstatus.hpp index 664808f0..045bf68e 100644 --- a/shared/src/traintastic/enum/commandstationstatus.hpp +++ b/shared/src/traintastic/enum/commandstationstatus.hpp @@ -40,4 +40,12 @@ struct EnumName 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 diff --git a/shared/src/traintastic/enum/decoderprotocol.hpp b/shared/src/traintastic/enum/decoderprotocol.hpp index 29f4859f..592ea833 100644 --- a/shared/src/traintastic/enum/decoderprotocol.hpp +++ b/shared/src/traintastic/enum/decoderprotocol.hpp @@ -30,10 +30,10 @@ enum class DecoderProtocol : uint8_t { Auto = 0, DCC = 1, - Motorola = 2, - MFX = 3, - Selectrix = 4, - FMZ = 5, + //Motorola = 2, + //MFX = 3, + //Selectrix = 4, + //FMZ = 5, Custom = 255, }; @@ -43,4 +43,11 @@ struct EnumName static constexpr char const* value = "decoder_protocol"; }; +ENUM_VALUES(DecoderProtocol, 3, +{ + {DecoderProtocol::Auto, "AUTO"}, + {DecoderProtocol::DCC, "DCC"}, + {DecoderProtocol::Custom, "CUSTOM"}, +}) + #endif diff --git a/shared/src/traintastic/enum/direction.hpp b/shared/src/traintastic/enum/direction.hpp index b3e1c0cf..781dd40f 100644 --- a/shared/src/traintastic/enum/direction.hpp +++ b/shared/src/traintastic/enum/direction.hpp @@ -38,4 +38,10 @@ struct EnumName static constexpr char const* value = "direction"; }; +ENUM_VALUES(Direction, 2, +{ + {Direction::Forward, "forward"}, + {Direction::Reverse, "reverse"}, +}) + #endif diff --git a/shared/src/traintastic/enum/enum.hpp b/shared/src/traintastic/enum/enum.hpp index 7aa57378..b45c8f5a 100644 --- a/shared/src/traintastic/enum/enum.hpp +++ b/shared/src/traintastic/enum/enum.hpp @@ -24,10 +24,32 @@ #ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ENUM_HPP #define TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_ENUM_HPP +#include + +#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 struct EnumName { static_assert(sizeof(T) != sizeof(T), "template specialization required"); }; +template +struct EnumValues +{ + static_assert(sizeof(T) != sizeof(T), "template specialization required"); +}; + #endif diff --git a/shared/src/traintastic/enum/lengthunit.hpp b/shared/src/traintastic/enum/lengthunit.hpp index 70e03869..d4e786f3 100644 --- a/shared/src/traintastic/enum/lengthunit.hpp +++ b/shared/src/traintastic/enum/lengthunit.hpp @@ -41,4 +41,14 @@ struct EnumName 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 diff --git a/shared/src/traintastic/enum/loconetcommandstation.hpp b/shared/src/traintastic/enum/loconetcommandstation.hpp index 433b0cdb..aa091ad1 100644 --- a/shared/src/traintastic/enum/loconetcommandstation.hpp +++ b/shared/src/traintastic/enum/loconetcommandstation.hpp @@ -25,18 +25,22 @@ #include #include "enum.hpp" +#include enum class LocoNetCommandStation : uint16_t { Custom = 0, UhlenbrockIntellibox = 1, - DigiKeijsDR5000 = 2, + DigikeijsDR5000 = 2, }; -template<> -struct EnumName +ENUM_NAME(LocoNetCommandStation, "loconet_command_station") + +ENUM_VALUES(LocoNetCommandStation, 3, { - static constexpr char const* value = "loconet_command_station"; -}; + {LocoNetCommandStation::Custom, "custom"}, + {LocoNetCommandStation::UhlenbrockIntellibox, "uhlenbrock_intellibox"}, + {LocoNetCommandStation::DigikeijsDR5000, "digikeijs_dr5000"}, +}) #endif diff --git a/shared/src/traintastic/enum/loconetserialinterface.hpp b/shared/src/traintastic/enum/loconetserialinterface.hpp index 288403f1..7f2b0665 100644 --- a/shared/src/traintastic/enum/loconetserialinterface.hpp +++ b/shared/src/traintastic/enum/loconetserialinterface.hpp @@ -29,14 +29,17 @@ enum class LocoNetSerialInterface : uint16_t { Custom = 0, - DigiKeijsDR5000 = 1, + DigikeijsDR5000 = 1, RoSoftLocoNetInterface = 2, }; -template<> -struct EnumName +ENUM_NAME(LocoNetSerialInterface, "loconet_serial_interface") + +ENUM_VALUES(LocoNetSerialInterface, 3, { - static constexpr char const* value = "loconet_serial_interface"; -}; + {LocoNetSerialInterface::Custom, "custom"}, + {LocoNetSerialInterface::DigikeijsDR5000, "digikeijs_dr5000"}, + {LocoNetSerialInterface::RoSoftLocoNetInterface, "rosoft_loconet_interface"}, +}) #endif diff --git a/shared/src/traintastic/enum/serialflowcontrol.hpp b/shared/src/traintastic/enum/serialflowcontrol.hpp index bc8070af..6ccb802e 100644 --- a/shared/src/traintastic/enum/serialflowcontrol.hpp +++ b/shared/src/traintastic/enum/serialflowcontrol.hpp @@ -20,30 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - /** - * shared/src/enum/serialflowcontrol.hpp - * - * This file is part of the traintastic source code. - * - * Copyright (C) 2019-2020 Reinder Feenstra - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef TRAINTASTIC_SHARED_ENUM_serialflowcontrol_HPP -#define traintastic_shared_enum_serialflowcontrol_hpp +#ifndef TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_SERIALFLOWCONTROL_HPP +#define TRAINTASTIC_SHARED_TRAINTASTIC_ENUM_SERIALFLOWCONTROL_HPP #include #include "enum.hpp" @@ -54,10 +32,12 @@ enum class SerialFlowControl : uint8_t Hardware = 1, }; -template<> -struct EnumName +ENUM_NAME(SerialFlowControl, "serial_flow_control") + +ENUM_VALUES(SerialFlowControl, 2, { - static constexpr char const* value = "serial_flow_control"; -}; + {SerialFlowControl::None, "none"}, + {SerialFlowControl::Hardware, "hardware"}, +}) #endif diff --git a/shared/src/traintastic/enum/speedunit.hpp b/shared/src/traintastic/enum/speedunit.hpp index 7b384786..b1c14a0f 100644 --- a/shared/src/traintastic/enum/speedunit.hpp +++ b/shared/src/traintastic/enum/speedunit.hpp @@ -38,4 +38,11 @@ struct EnumName static constexpr char const* value = "speed_unit"; }; +ENUM_VALUES(SpeedUnit, 3, +{ + {SpeedUnit::MeterPerSecond, "mps"}, + {SpeedUnit::KiloMeterPerHour, "kmph"}, + {SpeedUnit::MilePerHour, "mph"}, +}) + #endif diff --git a/shared/src/traintastic/enum/weightunit.hpp b/shared/src/traintastic/enum/weightunit.hpp index 4644ce8e..792240b4 100644 --- a/shared/src/traintastic/enum/weightunit.hpp +++ b/shared/src/traintastic/enum/weightunit.hpp @@ -39,4 +39,12 @@ struct EnumName 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 diff --git a/shared/src/traintastic/enum/worldevent.hpp b/shared/src/traintastic/enum/worldevent.hpp index 459f1813..8459285a 100644 --- a/shared/src/traintastic/enum/worldevent.hpp +++ b/shared/src/traintastic/enum/worldevent.hpp @@ -43,4 +43,15 @@ struct EnumName 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 diff --git a/shared/src/traintastic/enum/worldscale.hpp b/shared/src/traintastic/enum/worldscale.hpp index 77530d55..3eb14e22 100644 --- a/shared/src/traintastic/enum/worldscale.hpp +++ b/shared/src/traintastic/enum/worldscale.hpp @@ -41,4 +41,13 @@ struct EnumName 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 diff --git a/shared/src/traintastic/enum/xpressnetcommandstation.hpp b/shared/src/traintastic/enum/xpressnetcommandstation.hpp index 881a6b98..5da47907 100644 --- a/shared/src/traintastic/enum/xpressnetcommandstation.hpp +++ b/shared/src/traintastic/enum/xpressnetcommandstation.hpp @@ -30,6 +30,7 @@ enum class XpressNetCommandStation : uint16_t { Custom = 0, Roco10764 = 1, + DigikeijsDR5000 = 2, }; template<> @@ -38,4 +39,11 @@ struct EnumName static constexpr char const* value = "xpressnet_command_station"; }; +ENUM_VALUES(XpressNetCommandStation, 3, +{ + {XpressNetCommandStation::Custom, "custom"}, + {XpressNetCommandStation::Roco10764, "roco_10764"}, + {XpressNetCommandStation::DigikeijsDR5000, "digikeijs_dr5000"}, +}) + #endif diff --git a/shared/src/traintastic/enum/xpressnetserialinterface.hpp b/shared/src/traintastic/enum/xpressnetserialinterface.hpp index 55454cf9..09ecf23d 100644 --- a/shared/src/traintastic/enum/xpressnetserialinterface.hpp +++ b/shared/src/traintastic/enum/xpressnetserialinterface.hpp @@ -41,4 +41,13 @@ struct EnumName 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