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

traintastic / traintastic / 23669027368

27 Mar 2026 09:50PM UTC coverage: 26.198% (+0.02%) from 26.176%
23669027368

push

github

reinder
Merge remote-tracking branch 'origin/master' into cbus

11 of 144 new or added lines in 34 files covered. (7.64%)

1 existing line in 1 file now uncovered.

8256 of 31514 relevant lines covered (26.2%)

182.55 hits per line

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

0.0
/server/src/hardware/protocol/traintasticdiy/iohandler/simulationiohandler.cpp
1
/**
2
 * server/src/hardware/protocol/traintasticdiy/iohandler/simulationiohandler.cpp
3
 *
4
 * This file is part of the traintastic source code.
5
 *
6
 * Copyright (C) 2022-2024 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
#include "simulationiohandler.hpp"
24
#include "../kernel.hpp"
25
#include "../messages.hpp"
26
#include <version.hpp>
27

28
namespace TraintasticDIY {
29

30
static std::shared_ptr<std::byte[]> copy(const Message& message)
×
31
{
32
  auto* bytes = new std::byte[message.size()];
×
33
  std::memcpy(bytes, &message, message.size());
×
34
  return std::shared_ptr<std::byte[]>{bytes};
×
35
}
36

37
SimulationIOHandler::SimulationIOHandler(Kernel& kernel)
×
38
  : IOHandler(kernel)
×
39
{
40
}
×
41

42
void SimulationIOHandler::start()
×
43
{
44
  m_kernel.started();
×
45
}
×
46

47
bool SimulationIOHandler::send(const Message& message)
×
48
{
49
  switch(message.opCode)
×
50
  {
51
    case OpCode::Heartbeat:
×
52
      reply(Heartbeat());
×
53
      break;
×
54

55
    case OpCode::GetInputState:
×
56
    {
57
      const auto& getInputState = static_cast<const GetInputState&>(message);
×
58
      reply(SetInputState(getInputState.address(), InputState::Invalid));
×
59
      break;
×
60
    }
61
    case OpCode::GetOutputState:
×
62
    {
63
      const auto& getOutputState = static_cast<const GetOutputState&>(message);
×
64
      reply(SetOutputState(getOutputState.address(), OutputState::Invalid));
×
65
      break;
×
66
    }
67
    case OpCode::SetOutputState:
×
68
    {
69
#ifndef NDEBUG
70
      const auto& setOutputState = static_cast<const SetOutputState&>(message);
×
71
      assert(setOutputState.state == OutputState::False || setOutputState.state == OutputState::True);
×
72
#endif
73
      reply(message);
×
74
      break;
×
75
    }
76
    case OpCode::ThrottleSubUnsub:
×
77
    {
78
      // TODO
79
      break;
×
80
    }
81
    case OpCode::ThrottleSetFunction:
×
82
    {
83
      // TODO
84
      break;
×
85
    }
86
    case OpCode::ThrottleSetSpeedDirection:
×
87
    {
88
      // TODO
89
      break;
×
90
    }
91
    case OpCode::GetFeatures:
×
92
    {
93
      reply(Features(FeatureFlags1::Input | FeatureFlags1::Output));
×
94
      break;
×
95
    }
96
    case OpCode::GetInfo:
×
97
    {
98
      constexpr std::string_view text{"Traintastic DIY simulator v" TRAINTASTIC_VERSION};
×
99
      static_assert(text.size() <= 255);
100
      auto info = std::make_unique<std::byte[]>(sizeof(InfoBase) + text.size() + sizeof(Checksum));
×
101
      auto& infoBase = *reinterpret_cast<InfoBase*>(info.get());
×
102
      infoBase.opCode = OpCode::Info;
×
103
      infoBase.length = text.length();
×
104
      std::memcpy(info.get() + sizeof(InfoBase), text.data(), text.size());
×
105
      updateChecksum(infoBase);
×
106
      reply(infoBase);
×
107
      break;
×
108
    }
×
109
    case OpCode::SetInputState:
×
110
    case OpCode::Features:
111
    case OpCode::Info:
112
      assert(false); // only send by device
×
113
      break;
114
  }
115

116
  return true;
×
117
}
118

119
void SimulationIOHandler::reply(const Message& message)
×
120
{
121
  // post the reply, so it has some delay
122
  //! \todo better delay simulation? at least message transfer time?
NEW
123
  boost::asio::post(m_kernel.ioContext(), 
×
124
    [this, data=copy(message)]()
×
125
    {
126
      m_kernel.receive(*reinterpret_cast<const Message*>(data.get()));
×
127
    });
×
128
}
×
129

130
}
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