• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

traintastic / traintastic / 23170091702

16 Mar 2026 10:43PM UTC coverage: 26.544% (-0.07%) from 26.616%
23170091702

push

github

reinder
[cbus] added initialization states (for future proof smooth startup without flooding the bus with messages)

0 of 88 new or added lines in 5 files covered. (0.0%)

22 existing lines in 5 files now uncovered.

8246 of 31065 relevant lines covered (26.54%)

185.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/server/src/hardware/protocol/cbus/cbuskernel.hpp
1
/**
2
 * This file is part of Traintastic,
3
 * see <https://github.com/traintastic/traintastic>.
4
 *
5
 * Copyright (C) 2026 Reinder Feenstra
6
 *
7
 * This program is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU General Public License
9
 * as published by the Free Software Foundation; either version 2
10
 * of the License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
 */
21

22
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_CBUS_CBUSKERNEL_HPP
23
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_CBUS_CBUSKERNEL_HPP
24

25
#include "../kernelbase.hpp"
26
#include <map>
27
#include <span>
28
#include <set>
29
#include <optional>
30
#include <boost/asio/steady_timer.hpp>
31
#include <traintastic/enum/direction.hpp>
32
#include "cbusconfig.hpp"
33
#include "iohandler/cbusiohandler.hpp"
34

35
namespace CBUS {
36

37
class Kernel : public ::KernelBase
38
{
39
public:
40
  std::function<void()> onTrackOff;
41
  std::function<void()> onTrackOn;
42
  std::function<void()> onEmergencyStop;
43
  std::function<void(uint16_t address, bool isLongAddress)> onEngineSessionCancelled;
44
  std::function<void(uint16_t eventNumber, bool on)> onShortEvent;
45
  std::function<void(uint16_t nodeNumber, uint16_t eventNumber, bool on)> onLongEvent;
46

47
  /**
48
   * @brief Create kernel and IO handler
49
   *
50
   * @param[in] config CBUS configuration
51
   * @param[in] args IO handler arguments
52
   * @return The kernel instance
53
   */
54
  template<class IOHandlerType, class... Args>
55
  static std::unique_ptr<Kernel> create(std::string logId_, const Config& config, Args... args)
×
56
  {
57
    static_assert(std::is_base_of_v<IOHandler, IOHandlerType>);
58
    std::unique_ptr<Kernel> kernel{new Kernel(std::move(logId_), config, isSimulation<IOHandlerType>())};
×
59
    kernel->setIOHandler(std::make_unique<IOHandlerType>(*kernel, std::forward<Args>(args)...));
×
60
    return kernel;
×
61
  }
×
62

63
#ifndef NDEBUG
64
  bool isKernelThread() const
×
65
  {
66
    return std::this_thread::get_id() == m_thread.get_id();
×
67
  }
68
#endif
69

70
  /**
71
   * @brief Set CBUS configuration
72
   *
73
   * @param[in] config The CBUS configuration
74
   */
75
  void setConfig(const Config& config);
76

77
  /**
78
   * @brief Start the kernel and IO handler
79
   */
80
  void start();
81

82
  /**
83
   * @brief Stop the kernel and IO handler
84
   */
85
  void stop();
86

87
  /**
88
   * \brief Notify kernel the IO handler is started.
89
   * \note This function must run in the kernel's IO context
90
   */
91
  void started() final;
92

93
  void receive(uint8_t canId, const Message& message);
94

95
  void trackOff();
96
  void trackOn();
97
  void requestEmergencyStop();
98

99
  void setEngineSpeedDirection(uint16_t address, bool longAddress, uint8_t speedStep, uint8_t speedSteps, bool eStop, bool directionForward);
100
  void setEngineFunction(uint16_t address, bool longAddress, uint8_t number, bool value);
101

102
  void setAccessoryShort(uint16_t deviceNumber, bool on);
103
  void setAccessory(uint16_t nodeNumber, uint16_t eventNumber, bool on);
104

105
  bool send(std::vector<uint8_t> message);
106
  bool sendDCC(std::vector<uint8_t> dccPacket, uint8_t repeat);
107

108
private:
109
  //! Startup states, executed in order.
110
  enum class State
111
  {
112
    Initial, // must be first
113
    QueryNodes,
114
    GetCommandStationStatus,
115
    Started // must be last
116
  };
117

118
  struct Engine
119
  {
120
    std::optional<uint8_t> session;
121
    uint8_t speed = 0;
122
    uint8_t speedSteps = 126;
123
    bool directionForward = true;
124
    std::map<uint8_t, bool> functions;
125
    std::chrono::steady_clock::time_point lastCommand;
126
  };
127

128
  std::unique_ptr<IOHandler> m_ioHandler;
129
  const bool m_simulation;
130
  State m_state = State::Initial;
131
  boost::asio::steady_timer m_initializationTimer;
132
  Config m_config;
133
  bool m_trackOn = false;
134
  uint8_t m_engineKeepAliveSession;
135
  bool m_engineKeepAliveTimerActive = false;
136
  boost::asio::steady_timer m_engineKeepAliveTimer;
137
  std::map<uint16_t, Engine> m_engines;
138
  std::set<uint16_t> m_engineGLOCs;
139

140
  Kernel(std::string logId_, const Config& config, bool simulation);
141

142
  Kernel(const Kernel&) = delete;
143
  Kernel& operator =(const Kernel&) = delete;
144

145
  void setIOHandler(std::unique_ptr<IOHandler> handler);
146

147
  void send(const Message& message);
148
  void sendGetEngineSession(uint16_t address, bool longAddress);
149
  void sendSetEngineSessionMode(uint8_t session, uint8_t speedSteps);
150
  void sendSetEngineSpeedDirection(uint8_t session, uint8_t speed, bool directionForward);
151
  void sendSetEngineFunction(uint8_t session, uint8_t number, bool value);
152

NEW
153
  inline void nextState()
×
154
  {
NEW
155
    assert(m_state != State::Started);
×
NEW
156
    changeState(static_cast<State>(static_cast<std::underlying_type_t<State>>(m_state) + 1));
×
NEW
157
  }
×
158

159
  void changeState(State value);
160

161
  void restartInitializationTimer(std::chrono::milliseconds timeout);
162
  void restartEngineKeepAliveTimer();
163
};
164

165
}
166

167
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc