[cbus] added Lua support for sending CBUS/VLCB message and DCC commands
Einige Prüfungen sind fehlgeschlagen
Build / client macos-15-arm64 (push) Has been cancelled
Build / client macos-15-intel (push) Has been cancelled
Build / client ubuntu_24.04 (push) Has been cancelled
Build / client ubuntu_24.04_arm64 (push) Has been cancelled
Build / client raspberrypios_arm64 (push) Has been cancelled
Build / client raspberrypios_arm7 (push) Has been cancelled
Build / client windows_x64_msvc (push) Has been cancelled
Build / server ubuntu_24.04 (debug+ccov) (push) Has been cancelled
Build / server macos-15-arm64 (push) Has been cancelled
Build / server macos-15-intel (push) Has been cancelled
Build / server raspberrypios_arm64 (push) Has been cancelled
Build / server raspberrypios_arm7 (push) Has been cancelled
Build / server ubuntu_24.04 (push) Has been cancelled
Build / server ubuntu_24.04_arm64 (push) Has been cancelled
Build / server windows_x64_clang (push) Has been cancelled
Build / language files (push) Has been cancelled
Build / manual (push) Has been cancelled
Build / Update contributers in README.md (push) Has been cancelled
Build / shared data raspberrypios_10 (push) Has been cancelled
Build / shared data ubuntu_24.04 (push) Has been cancelled
Build / package innosetup (push) Has been cancelled
Build / Deploy to website (push) Has been cancelled
Einige Prüfungen sind fehlgeschlagen
Build / client macos-15-arm64 (push) Has been cancelled
Build / client macos-15-intel (push) Has been cancelled
Build / client ubuntu_24.04 (push) Has been cancelled
Build / client ubuntu_24.04_arm64 (push) Has been cancelled
Build / client raspberrypios_arm64 (push) Has been cancelled
Build / client raspberrypios_arm7 (push) Has been cancelled
Build / client windows_x64_msvc (push) Has been cancelled
Build / server ubuntu_24.04 (debug+ccov) (push) Has been cancelled
Build / server macos-15-arm64 (push) Has been cancelled
Build / server macos-15-intel (push) Has been cancelled
Build / server raspberrypios_arm64 (push) Has been cancelled
Build / server raspberrypios_arm7 (push) Has been cancelled
Build / server ubuntu_24.04 (push) Has been cancelled
Build / server ubuntu_24.04_arm64 (push) Has been cancelled
Build / server windows_x64_clang (push) Has been cancelled
Build / language files (push) Has been cancelled
Build / manual (push) Has been cancelled
Build / Update contributers in README.md (push) Has been cancelled
Build / shared data raspberrypios_10 (push) Has been cancelled
Build / shared data ubuntu_24.04 (push) Has been cancelled
Build / package innosetup (push) Has been cancelled
Build / Deploy to website (push) Has been cancelled
Dieser Commit ist enthalten in:
Ursprung
81d452bad1
Commit
222c219fb7
@ -221,6 +221,7 @@ class TraintasticHelp:
|
||||
]},
|
||||
{'Product index': 'appendix/supported-hardware/product-index.md'}
|
||||
]},
|
||||
{'CBUS/VLCB reference': 'appendix/cbus-vlcb.md'},
|
||||
{'LocoNet reference': 'appendix/loconet.md'},
|
||||
{'XpressNet reference': 'appendix/xpressnet.md'},
|
||||
{'Lua scripting reference': lua_ref},
|
||||
|
||||
44
manual/docs/en/appendix/cbus-vlcb.md
Normale Datei
44
manual/docs/en/appendix/cbus-vlcb.md
Normale Datei
@ -0,0 +1,44 @@
|
||||
# CBUS/VLCB reference
|
||||
|
||||
CBUS is a Layout Control Bus developed by members of the Model Electronic Railway Group (MERG).
|
||||
CBUS uses the Controller Area Network (CAN) for communication between the CBUS modules.
|
||||
|
||||
VLCB is an CBUS extension developed by MERG members to it adds additional commands and introduced a a stricter priority system for commands.
|
||||
|
||||
This appendix does **not** explain the CBUS/VLCB protocol.
|
||||
Instead, it **how Traintastic implements and uses CBUS/VLCB** and which protocol messages are recognized.
|
||||
It is intended for advanced users who are already familiar with the basics of the CBUS/VLCB protocol.
|
||||
|
||||
## Supported hardware
|
||||
|
||||
*TODO: under development*
|
||||
|
||||
## Message support
|
||||
|
||||
### General control
|
||||
- Track on/off: `TOF`, `TON`, `RTOF`, `RTON` - Supported
|
||||
- Emergency stop: `ESTOP`, `RESTP` - Supported
|
||||
|
||||
*TODO: under development, will be expanded when implemented*
|
||||
|
||||
## Debugging and monitoring
|
||||
|
||||
Traintastic provides a debug option for CBUS/VLCB that logs all bus traffic.
|
||||
Messages are shown in **hexadecimal format**, and for many message types a human-readable textual description of the content is also provided.
|
||||
|
||||
This is useful for:
|
||||
|
||||
- Diagnosing compatibility issues with specific modules.
|
||||
- Verifying that messages are transmitted and received as expected.
|
||||
|
||||
### Sending raw messages
|
||||
|
||||
Through [**Lua scripting**](../advanced/scripting-basics.md), it is also possible to:
|
||||
|
||||
- Send **raw CBUS/VLCB messages**, see [`send()`](lua/object/cbusinterface.md#send).
|
||||
- Send **raw DCC track commands** (`RDCCn`), see [`send_dcc()`](lua/object/cbusinterface.md#send_dcc).
|
||||
|
||||
!!! warning "Use this with caution!"
|
||||
- These messages bypass Traintastic’s normal handling.
|
||||
- You need a solid understanding of CBUS/VLCB and DCC to avoid conflicts.
|
||||
- Side effects may occur that Traintastic is not aware of or cannot manage.
|
||||
@ -106,6 +106,9 @@
|
||||
"CLOCK": {
|
||||
"type": "constant"
|
||||
},
|
||||
"CBUS_INTERFACE": {
|
||||
"type": "constant"
|
||||
},
|
||||
"DCCEX_INTERFACE": {
|
||||
"type": "constant"
|
||||
},
|
||||
@ -228,4 +231,4 @@
|
||||
"type": "constant",
|
||||
"since": "0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
manual/luadoc/object/cbusinterface.json
Normale Datei
23
manual/luadoc/object/cbusinterface.json
Normale Datei
@ -0,0 +1,23 @@
|
||||
{
|
||||
"send": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "message"
|
||||
}
|
||||
],
|
||||
"return_values": 1
|
||||
},
|
||||
"send_dcc": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "dcc_packet"
|
||||
},
|
||||
{
|
||||
"name": "repeat",
|
||||
"optional": true,
|
||||
"default": 2
|
||||
}
|
||||
],
|
||||
"return_values": 1
|
||||
}
|
||||
}
|
||||
@ -3190,5 +3190,58 @@
|
||||
{
|
||||
"term": "object.category.signals:title",
|
||||
"definition": "Signals"
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface:title",
|
||||
"definition": "CBUS/VLCB interface"
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface:description",
|
||||
"definition": "Interface for communicating with a CBUS/VLCB network."
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send_dcc:description",
|
||||
"definition": "Request the command station to send a DCC packet to the track (`RDCCn`)."
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send_dcc.parameter.dcc_packet:description",
|
||||
"definition": "Table containing two to five DCC packet bytes to send excluding checksum byte."
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send_dcc.parameter.repeat:description",
|
||||
"definition": "Number of times to repeat the packet on the track. (1...255)"
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send_dcc:return_values",
|
||||
"definition": "`true` if send, `false` otherwise."
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send_dcc.warning:title",
|
||||
"definition": "Use this with caution!"
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send_dcc.warning:description",
|
||||
"definition": "These messages bypass Traintastic’s normal handling. You need a solid understanding of DCC to avoid conflicts. Side effects may occur that Traintastic is not aware of or cannot manage."
|
||||
},
|
||||
|
||||
{
|
||||
"term": "object.cbusinterface.send:description",
|
||||
"definition": "Send CBUS/VLCB message."
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send.parameter.message:description",
|
||||
"definition": "CBUS/VLCB message bytes. (1...8)"
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send:return_values",
|
||||
"definition": "`true` if send, `false` otherwise."
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send.warning:title",
|
||||
"definition": "Use this with caution!"
|
||||
},
|
||||
{
|
||||
"term": "object.cbusinterface.send.warning:description",
|
||||
"definition": "These messages bypass Traintastic’s normal handling. You need a solid understanding of CBUS/VLCB to avoid conflicts. Side effects may occur that Traintastic is not aware of or cannot manage."
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@ -36,6 +36,10 @@
|
||||
#include "../../utils/displayname.hpp"
|
||||
#include "../../world/world.hpp"
|
||||
|
||||
namespace CBUS {
|
||||
class Simulator{};
|
||||
}
|
||||
|
||||
CREATE_IMPL(CBUSInterface)
|
||||
|
||||
CBUSInterface::CBUSInterface(World& world, std::string_view _id)
|
||||
@ -88,6 +92,24 @@ CBUSInterface::CBUSInterface(World& world, std::string_view _id)
|
||||
|
||||
CBUSInterface::~CBUSInterface() = default;
|
||||
|
||||
bool CBUSInterface::send(std::vector<uint8_t> message)
|
||||
{
|
||||
if(m_kernel)
|
||||
{
|
||||
return m_kernel->send(std::move(message));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBUSInterface::sendDCC(std::vector<uint8_t> dccPacket, uint8_t repeat)
|
||||
{
|
||||
if(m_kernel)
|
||||
{
|
||||
return m_kernel->sendDCC(std::move(dccPacket), repeat);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CBUSInterface::addToWorld()
|
||||
{
|
||||
Interface::addToWorld();
|
||||
|
||||
@ -30,7 +30,7 @@ class CBUSSettings;
|
||||
|
||||
namespace CBUS {
|
||||
class Kernel;
|
||||
class Simulator {};
|
||||
class Simulator;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,6 +53,17 @@ public:
|
||||
CBUSInterface(World& world, std::string_view _id);
|
||||
~CBUSInterface() final;
|
||||
|
||||
//! \brief Send CBUS/VLCB message
|
||||
//! \param[in] message CBUS/VLCB message bytes, 1..8 bytes.
|
||||
//! \return \c true if send, \c false otherwise.
|
||||
bool send(std::vector<uint8_t> message);
|
||||
|
||||
//! \brief Send DCC packet
|
||||
//! \param[in] dccPacket DCC packet byte, exluding checksum. Length is limited to 6.
|
||||
//! \param[in] repeat DCC packet repeat count 0..7
|
||||
//! \return \c true if send, \c false otherwise.
|
||||
bool sendDCC(std::vector<uint8_t> dccPacket, uint8_t repeat);
|
||||
|
||||
protected:
|
||||
void addToWorld() final;
|
||||
void loaded() final;
|
||||
|
||||
@ -25,9 +25,11 @@
|
||||
/*
|
||||
#include "simulator/cbussimulator.hpp"
|
||||
*/
|
||||
#include "../dcc/dcc.hpp"
|
||||
#include "../../../core/eventloop.hpp"
|
||||
#include "../../../log/log.hpp"
|
||||
#include "../../../log/logmessageexception.hpp"
|
||||
#include "../../../utils/inrange.hpp"
|
||||
#include "../../../utils/setthreadname.hpp"
|
||||
|
||||
namespace CBUS {
|
||||
@ -191,6 +193,65 @@ void Kernel::requestEmergencyStop()
|
||||
});
|
||||
}
|
||||
|
||||
bool Kernel::send(std::vector<uint8_t> message)
|
||||
{
|
||||
assert(isEventLoopThread());
|
||||
|
||||
if(!inRange<size_t>(message.size(), 1, 8))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ioContext.post(
|
||||
[this, msg=std::move(message)]()
|
||||
{
|
||||
send(*reinterpret_cast<const Message*>(msg.data()));
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Kernel::sendDCC(std::vector<uint8_t> dccPacket, uint8_t repeat)
|
||||
{
|
||||
assert(isEventLoopThread());
|
||||
|
||||
if(!inRange<size_t>(dccPacket.size(), 2, 5) || repeat == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dccPacket.emplace_back(DCC::calcChecksum(dccPacket));
|
||||
|
||||
m_ioContext.post(
|
||||
[this, packet=std::move(dccPacket), repeat]()
|
||||
{
|
||||
switch(packet.size())
|
||||
{
|
||||
case 3:
|
||||
send(RequestDCCPacket<3>(packet, repeat));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
send(RequestDCCPacket<4>(packet, repeat));
|
||||
break;
|
||||
|
||||
case 5:
|
||||
send(RequestDCCPacket<5>(packet, repeat));
|
||||
break;
|
||||
|
||||
case 6:
|
||||
send(RequestDCCPacket<6>(packet, repeat));
|
||||
break;
|
||||
|
||||
default: [[unlikely]]
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Kernel::setIOHandler(std::unique_ptr<IOHandler> handler)
|
||||
{
|
||||
assert(isEventLoopThread());
|
||||
|
||||
@ -89,6 +89,9 @@ public:
|
||||
void trackOn();
|
||||
void requestEmergencyStop();
|
||||
|
||||
bool send(std::vector<uint8_t> message);
|
||||
bool sendDCC(std::vector<uint8_t> dccPacket, uint8_t repeat);
|
||||
|
||||
private:
|
||||
std::unique_ptr<IOHandler> m_ioHandler;
|
||||
const bool m_simulation;
|
||||
|
||||
@ -24,5 +24,6 @@
|
||||
|
||||
#include "messages/cbusenginemessages.hpp"
|
||||
#include "messages/cbusgeneralmessages.hpp"
|
||||
#include "messages/cbusrequestdccpacketmessage.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* Copyright (C) 2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_CBUS_MESSAGES_CBUSREQUESTDCCPACKETMESSAGE_HPP
|
||||
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_CBUS_MESSAGES_CBUSREQUESTDCCPACKETMESSAGE_HPP
|
||||
|
||||
#include "cbusmessage.hpp"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <span>
|
||||
|
||||
namespace CBUS {
|
||||
|
||||
template<size_t N>
|
||||
requires(N >= 3 && N <= 6)
|
||||
struct RequestDCCPacket : Message
|
||||
{
|
||||
uint8_t repeat;
|
||||
uint8_t data[N];
|
||||
|
||||
RequestDCCPacket(std::span<const uint8_t> bytes, uint8_t repeat_)
|
||||
: Message(RDCCn())
|
||||
, repeat{repeat_}
|
||||
{
|
||||
assert(N == bytes.size());
|
||||
std::memcpy(data, bytes.data(), N);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr OpCode RDCCn() noexcept
|
||||
{
|
||||
switch(N)
|
||||
{
|
||||
case 3: return OpCode::RDCC3;
|
||||
case 4: return OpCode::RDCC4;
|
||||
case 5: return OpCode::RDCC5;
|
||||
case 6: return OpCode::RDCC6;
|
||||
}
|
||||
return static_cast<OpCode>(0); // unreachable, should never happen
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(RequestDCCPacket<3>) == 5);
|
||||
static_assert(sizeof(RequestDCCPacket<4>) == 6);
|
||||
static_assert(sizeof(RequestDCCPacket<5>) == 7);
|
||||
static_assert(sizeof(RequestDCCPacket<6>) == 8);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/hardware/protocol/dcc/dcc.hpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021,2023-2024 Reinder Feenstra
|
||||
* Copyright (C) 2021-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -24,6 +23,7 @@
|
||||
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_DCC_DCC_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <traintastic/enum/decoderprotocol.hpp>
|
||||
#include "../../../utils/inrange.hpp"
|
||||
|
||||
@ -45,6 +45,20 @@ constexpr DecoderProtocol getProtocol(uint16_t address)
|
||||
return isLongAddress(address) ? DecoderProtocol::DCCLong : DecoderProtocol::DCCShort;
|
||||
}
|
||||
|
||||
constexpr uint8_t calcChecksum(std::span<const uint8_t> message)
|
||||
{
|
||||
if(message.empty()) [[unlikely]]
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
uint8_t checksum = message[0];
|
||||
for(size_t i = 1; i < message.size(); i++)
|
||||
{
|
||||
checksum ^= message[i];
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
|
||||
namespace Accessory {
|
||||
|
||||
constexpr uint16_t addressMin = 1;
|
||||
|
||||
@ -62,6 +62,7 @@
|
||||
|
||||
#include "../clock/clock.hpp"
|
||||
|
||||
#include "../hardware/interface/cbusinterface.hpp"
|
||||
#include "../hardware/interface/dccexinterface.hpp"
|
||||
#include "../hardware/interface/ecosinterface.hpp"
|
||||
#include "../hardware/interface/hsi88.hpp"
|
||||
@ -196,6 +197,7 @@ void Class::registerValues(lua_State* L)
|
||||
registerValue<Clock>(L, "CLOCK");
|
||||
|
||||
// hardware - interface:
|
||||
registerValue<CBUSInterface>(L, "CBUS_INTERFACE");
|
||||
registerValue<DCCEXInterface>(L, "DCCEX_INTERFACE");
|
||||
registerValue<ECoSInterface>(L, "ECOS_INTERFACE");
|
||||
registerValue<HSI88Interface>(L, "HSI88_INTERFACE");
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/lua/object.cpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2025 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -24,6 +23,7 @@
|
||||
#include "object/object.hpp"
|
||||
#include "object/objectlist.hpp"
|
||||
#include "object/interface.hpp"
|
||||
#include "object/cbusinterface.hpp"
|
||||
#include "object/loconetinterface.hpp"
|
||||
#include "object/scriptthrottle.hpp"
|
||||
|
||||
@ -36,6 +36,7 @@ void registerTypes(lua_State* L)
|
||||
Object::registerType(L);
|
||||
ObjectList::registerType(L);
|
||||
Interface::registerType(L);
|
||||
CBUSInterface::registerType(L);
|
||||
LocoNetInterface::registerType(L);
|
||||
ScriptThrottle::registerType(L);
|
||||
|
||||
@ -65,7 +66,11 @@ void push(lua_State* L, const ObjectPtr& value)
|
||||
lua_pop(L, 1); // remove nil
|
||||
new(lua_newuserdata(L, sizeof(ObjectPtrWeak))) ObjectPtrWeak(value);
|
||||
|
||||
if(dynamic_cast<::LocoNetInterface*>(value.get()))
|
||||
if(dynamic_cast<::CBUSInterface*>(value.get()))
|
||||
{
|
||||
luaL_setmetatable(L, CBUSInterface::metaTableName);
|
||||
}
|
||||
else if(dynamic_cast<::LocoNetInterface*>(value.get()))
|
||||
luaL_setmetatable(L, LocoNetInterface::metaTableName);
|
||||
else if(dynamic_cast<AbstractObjectList*>(value.get()))
|
||||
luaL_setmetatable(L, ObjectList::metaTableName);
|
||||
|
||||
75
server/src/lua/object/cbusinterface.cpp
Normale Datei
75
server/src/lua/object/cbusinterface.cpp
Normale Datei
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* Copyright (C) 2026 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 "cbusinterface.hpp"
|
||||
#include "interface.hpp"
|
||||
#include "object.hpp"
|
||||
#include "../check.hpp"
|
||||
#include "../checkarguments.hpp"
|
||||
#include "../checkvector.hpp"
|
||||
#include "../push.hpp"
|
||||
#include "../to.hpp"
|
||||
#include "../metatable.hpp"
|
||||
|
||||
namespace Lua::Object {
|
||||
|
||||
void CBUSInterface::registerType(lua_State* L)
|
||||
{
|
||||
MetaTable::clone(L, Interface::metaTableName, metaTableName);
|
||||
lua_pushcfunction(L, __index);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
int CBUSInterface::index(lua_State* L, ::CBUSInterface& object)
|
||||
{
|
||||
const auto key = to<std::string_view>(L, 2);
|
||||
LUA_OBJECT_METHOD(send)
|
||||
LUA_OBJECT_METHOD(send_dcc)
|
||||
return Interface::index(L, object);
|
||||
}
|
||||
|
||||
int CBUSInterface::__index(lua_State* L)
|
||||
{
|
||||
return index(L, *check<::CBUSInterface>(L, 1));
|
||||
}
|
||||
|
||||
int CBUSInterface::send(lua_State* L)
|
||||
{
|
||||
checkArguments(L, 1);
|
||||
auto interface = check<::CBUSInterface>(L, lua_upvalueindex(1));
|
||||
auto message = checkVector<uint8_t>(L, 1);
|
||||
Lua::push(L, interface->send(std::move(message)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CBUSInterface::send_dcc(lua_State* L)
|
||||
{
|
||||
const uint8_t defaultRepeat = 2;
|
||||
const int argc = checkArguments(L, 1, 2);
|
||||
auto interface = check<::CBUSInterface>(L, lua_upvalueindex(1));
|
||||
auto dccPacket = checkVector<uint8_t>(L, 1);
|
||||
auto repeat = (argc >= 2) ? check<uint8_t>(L, 2) : defaultRepeat;
|
||||
Lua::push(L, interface->sendDCC(std::move(dccPacket), repeat));
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
48
server/src/lua/object/cbusinterface.hpp
Normale Datei
48
server/src/lua/object/cbusinterface.hpp
Normale Datei
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* Copyright (C) 2026 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_LUA_OBJECT_CBUSINTERFACE_HPP
|
||||
#define TRAINTASTIC_SERVER_LUA_OBJECT_CBUSINTERFACE_HPP
|
||||
|
||||
#include <lua.hpp>
|
||||
#include "../../hardware/interface/cbusinterface.hpp"
|
||||
|
||||
namespace Lua::Object {
|
||||
|
||||
class CBUSInterface
|
||||
{
|
||||
private:
|
||||
static int __index(lua_State* L);
|
||||
|
||||
static int send(lua_State* L);
|
||||
static int send_dcc(lua_State* L);
|
||||
|
||||
public:
|
||||
static constexpr char const* metaTableName = "object.interface.cbus";
|
||||
|
||||
static void registerType(lua_State* L);
|
||||
|
||||
static int index(lua_State* L, ::CBUSInterface& object);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren