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

traintastic / traintastic / 23667775307

27 Mar 2026 09:13PM UTC coverage: 28.009% (-0.002%) from 28.011%
23667775307

push

github

reinder
[boost] fix timer cancel() error_code overload is removed in 1.87, see #220

0 of 5 new or added lines in 1 file covered. (0.0%)

220 existing lines in 10 files now uncovered.

8182 of 29212 relevant lines covered (28.01%)

194.75 hits per line

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

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

23
#ifndef TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_Z21_SERVERKERNEL_HPP
24
#define TRAINTASTIC_SERVER_HARDWARE_PROTOCOL_Z21_SERVERKERNEL_HPP
25

26
#include "kernel.hpp"
27
#include <list>
28
#include <map>
29
#include <unordered_map>
30
#include <boost/asio/post.hpp>
31
#include <boost/asio/steady_timer.hpp>
32
#include <boost/signals2/signal.hpp>
33
#include <traintastic/enum/tristate.hpp>
34
#include "messages.hpp"
35

36
class DecoderList;
37

38
namespace Z21 {
39

40
class ServerKernel final : public Kernel
41
{
42
  private:
43
    struct Client
44
    {
45
      std::chrono::time_point<std::chrono::steady_clock> lastSeen;
46
      BroadcastFlags broadcastFlags = BroadcastFlags::None;
47
      std::list<std::pair<uint16_t, bool>> subscriptions;
48
    };
49

50
    struct DecoderSubscription
51
    {
52
      boost::signals2::connection connection;
53
      size_t count; //!< number of clients subscribed to the decoder
54
    };
55

56
    boost::asio::steady_timer m_inactiveClientPurgeTimer;
57
    ServerConfig m_config;
58
    std::shared_ptr<DecoderList> m_decoderList;
59
    std::unordered_map<IOHandler::ClientId, Client> m_clients;
60
    std::map<std::pair<uint16_t, bool>, DecoderSubscription> m_decoderSubscriptions;
61
    TriState m_trackPowerOn = TriState::Undefined;
62
    std::function<void()> m_onTrackPowerOff;
63
    std::function<void()> m_onTrackPowerOn;
64
    TriState m_emergencyStop = TriState::Undefined;
65
    std::function<void()> m_onEmergencyStop;
66

67
    ServerKernel(std::string logId_, const ServerConfig& config, std::shared_ptr<DecoderList> decoderList);
68

69
    void onStart() final;
70
    void onStop() final;
71

72
    template<class T>
UNCOV
73
    void postSendTo(const T& message, IOHandler::ClientId clientId)
×
74
    {
75
      boost::asio::post(m_ioContext, 
×
UNCOV
76
        [this, message, clientId]()
×
77
        {
UNCOV
78
          sendTo(message, clientId);
×
79
        });
UNCOV
80
    }
×
81

82
    void sendTo(const Message& message, IOHandler::ClientId clientId);
83
    void sendTo(const Message& message, BroadcastFlags broadcastFlags);
84

85
    LanSystemStateDataChanged getLanSystemStateDataChanged() const;
86

87
    std::shared_ptr<Decoder> getDecoder(uint16_t address, bool longAddress) const;
88

89
    void removeClient(IOHandler::ClientId clientId);
90
    void subscribe(IOHandler::ClientId clientId, uint16_t address, bool longAddress);
91
    void unsubscribe(IOHandler::ClientId clientId, std::pair<uint16_t, bool> key);
92
    void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber);
93

94
    void startInactiveClientPurgeTimer();
95
    void inactiveClientPurgeTimerExpired(const boost::system::error_code& ec);
96

97
  public:
98
    /**
99
     * @brief Create kernel and IO handler
100
     * @param[in] config Z21 server configuration
101
     * @param[in] args IO handler arguments
102
     * @return The kernel instance
103
     */
104
    template<class IOHandlerType, class... Args>
UNCOV
105
    static std::unique_ptr<ServerKernel> create(std::string logId_, const ServerConfig& config, std::shared_ptr<DecoderList> decoderList, Args... args)
×
106
    {
107
      static_assert(std::is_base_of_v<IOHandler, IOHandlerType>);
108
      std::unique_ptr<ServerKernel> kernel{new ServerKernel(std::move(logId_), config, std::move(decoderList))};
×
109
      kernel->setIOHandler(std::make_unique<IOHandlerType>(*kernel, std::forward<Args>(args)...));
×
110
      return kernel;
×
UNCOV
111
    }
×
112

113
    /**
114
     * @brief ...
115
     * @param[in] callback ...
116
     * @note This function may not be called when the kernel is running.
117
     */
UNCOV
118
    inline void setOnTrackPowerOff(std::function<void()> callback)
×
119
    {
120
      assert(!m_started);
×
121
      m_onTrackPowerOff = std::move(callback);
×
UNCOV
122
    }
×
123

124
    /**
125
     * @brief ...
126
     * @param[in] callback ...
127
     * @note This function may not be called when the kernel is running.
128
     */
UNCOV
129
    inline void setOnTrackPowerOn(std::function<void()> callback)
×
130
    {
131
      assert(!m_started);
×
132
      m_onTrackPowerOn = std::move(callback);
×
UNCOV
133
    }
×
134

135
    /**
136
     * @brief ...
137
     * @param[in] callback ...
138
     * @note This function may not be called when the kernel is running.
139
     */
UNCOV
140
    inline void setOnEmergencyStop(std::function<void()> callback)
×
141
    {
142
      assert(!m_started);
×
143
      m_onEmergencyStop = std::move(callback);
×
UNCOV
144
    }
×
145

146
    /**
147
     * @brief Set Z21 server configuration
148
     * @param[in] config The Z21 server configuration
149
     */
150
    void setConfig(const ServerConfig& config);
151

152
    /**
153
     * @brief Set Z21 state
154
     * @param[in] trackPowerOn \c true if track power is on, \c false if track power is off
155
     * @param[in] emergencyStop \c true if emergency stop is active, \c false if emergency stop isn't active
156
     */
157
    void setState(bool trackPowerOn, bool emergencyStop);
158

159
    /**
160
     * @brief Incoming message handler
161
     * This method must be called by the IO handler whenever a Z21 message is received.
162
     * @param[in] message The received Z21 message
163
     * @param[in] cliendId The client who sent the message
164
     * @note This function must run in the kernel's IO context
165
     */
166
    void receiveFrom(const Message& message, IOHandler::ClientId clientId);
167
};
168

169
}
170

171
#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