Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
TractionTrain.hxx
Go to the documentation of this file.
1
35#ifndef _OPENLCB_TRACTIONTRAIN_HXX_
36#define _OPENLCB_TRACTIONTRAIN_HXX_
37
38#include <set>
39
40#include "executor/Service.hxx"
42#include "openlcb/Node.hxx"
45
46namespace openlcb
47{
48
49
50class TrainService;
51
60class TrainNode : public Node
61{
62public:
63 ~TrainNode();
64
67 virtual TrainImpl *train() = 0;
68
82 virtual bool function_policy(NodeHandle src, uint8_t command_byte,
83 uint32_t fnum, uint16_t value, Notifiable *done) = 0;
84
88 virtual void command_hook(NodeHandle src, const Payload& p) = 0;
89
92
94 virtual void set_controller(NodeHandle id) = 0;
95
96 // Thread-safety information
97 //
98 // The consisting functionality is thread-compatible, which means that it
99 // is the responsibility of the caller to ensure that no two threads are
100 // calling these methods concurrently.
101 //
102 // In practice these methods are always called from the TractionService
103 // which only operates on a single thread (the service's executor) and will
104 // only process one request at a time. All traction protocol requests being
105 // forwarded and thus traversing the consist list will be fully processed
106 // before any consist change requests would reach the front of the queue
107 // for the traction flow.
108
113 virtual bool add_consist(NodeID tgt, uint8_t flags) = 0;
114
118 virtual bool remove_consist(NodeID tgt) = 0;
119
125 virtual NodeID query_consist(int id, uint8_t* flags) = 0;
126
128 virtual int query_consist_length() = 0;
129};
130
133struct ConsistEntry : public QMember
134{
138 ConsistEntry(NodeID s, uint8_t flags)
139 : payload((s << 8) | flags)
140 {
141 }
144 {
145 return payload >> 8;
146 }
148 uint8_t get_flags() const
149 {
150 return payload & 0xff;
151 }
154 void set_flags(uint8_t new_flags)
155 {
156 payload ^= (payload & 0xff);
157 payload |= new_flags;
158 }
159
160private:
162 uint64_t payload;
163};
164
168public:
170
173 bool function_policy(NodeHandle src, uint8_t command_byte, uint32_t fnum,
174 uint16_t value, Notifiable *done) override
175 {
176 AutoNotify an(done);
177 return true;
178 }
179
180 void command_hook(NodeHandle src, const Payload &p) override
181 {
182 }
183
186 bool add_consist(NodeID tgt, uint8_t flags) override
187 {
188 if (!tgt)
189 {
190 return false;
191 }
192 if (tgt == node_id())
193 {
194 return false;
195 }
196 auto it = consistSlaves_.begin();
197 for (; it != consistSlaves_.end(); ++it)
198 {
199 if (it->get_slave() == tgt)
200 {
201 it->set_flags(flags);
202 return false;
203 }
204 }
205 consistSlaves_.insert(it, new ConsistEntry(tgt, flags));
206 return true;
207 }
208
211 bool remove_consist(NodeID tgt) override
212 {
213 for (auto it = consistSlaves_.begin(); it != consistSlaves_.end(); ++it)
214 {
215 if (it->get_slave() == tgt)
216 {
217 auto* p = it.operator->();
218 consistSlaves_.erase(it);
219 delete p;
220 return true;
221 }
222 }
223 return false;
224 }
225
228 NodeID query_consist(int id, uint8_t* flags) override
229 {
230 int k = 0;
231 for (auto it = consistSlaves_.begin();
232 it != consistSlaves_.end(); ++it, ++k)
233 {
234 if (k == id)
235 {
236 if (flags) *flags = it->get_flags();
237 return it->get_slave();
238 }
239 }
240 return 0;
241 }
242
244 int query_consist_length() override
245 {
246 int ret = 0;
247 for (auto it = consistSlaves_.begin(); it != consistSlaves_.end();
248 ++it, ++ret)
249 {
250 }
251 return ret;
252 }
253
254 TypedQueue<ConsistEntry> consistSlaves_;
255};
256
259{
260public:
261 DefaultTrainNode(TrainService *service, TrainImpl *impl);
263
265 {
266 return controllerNodeId_;
267 }
268
269 void set_controller(NodeHandle id) override
270 {
272 }
273
274 If *iface() override;
275 bool is_initialized() override
276 {
277 return isInitialized_;
278 }
279 void set_initialized() override
280 {
281 isInitialized_ = 1;
282 }
283 // Used for restarting the stack.
284 void clear_initialized() override
285 {
286 isInitialized_ = 0;
287 }
288
289 TrainImpl *train() override
290 {
291 return train_;
292 }
293
294protected:
299
300private:
302 unsigned isInitialized_ : 1;
303
306};
307
310{
311public:
317
320
324};
325
329{
330public:
337
340
343 {
344 return nodeId_;
345 }
346
347private:
350};
351
357class TrainService : public Service, private Atomic
358{
359public:
365 If *iface, NodeRegistry *train_node_registry = new DefaultNodeRegistry);
367
368 If *iface()
369 {
370 return iface_;
371 }
372
375 void register_train(TrainNode *node);
376
379 void unregister_train(TrainNode *node);
380
386 {
387 return nodes_->is_node_registered(node);
388 }
389
390private:
391 struct Impl;
397 std::unique_ptr<NodeRegistry> nodes_;
398};
399
400} // namespace openlcb
401
402#endif // _OPENLCB_TRACTIONTRAIN_HXX_
Lightweight locking class for protecting small critical sections.
Definition Atomic.hxx:130
This class sends a notification in its destructor.
An object that can schedule itself on an executor to run.
Essentially a "next" pointer container.
Definition QMember.hxx:42
Collection of related state machines that pend on incoming messages.
A simple, fast, type-safe single-linked queue class with non-virtual methods.
Default implementation of a train node.
TrainImpl * train() override
void set_initialized() override
Callback from the node initialization flow when the node finished initialization.
NodeHandle get_controller() override
TrainService * service_
Pointer to the traction service.
void set_controller(NodeHandle id) override
NodeHandle controllerNodeId_
Controller node that is assigned to run this train. 0 if none.
TrainImpl * train_
Pointer to the train implementation object.
unsigned isInitialized_
Node is initialized bit for startup transient.
void clear_initialized() override
Callback from the simple stack when the node has to return to uninitialized state.
Abstract class representing an OpenLCB Interface.
Definition If.hxx:185
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
Abstract base class for train implementations.
Train node class with a an OpenLCB Node ID from the DCC pool. Used for command stations.
Intermediate class which is still abstract, but adds implementation for the consist management functi...
bool add_consist(NodeID tgt, uint8_t flags) override
Adds a node ID to the consist targets.
bool remove_consist(NodeID tgt) override
Removes a node ID from the consist targets.
void command_hook(NodeHandle src, const Payload &p) override
Invoked for every incoming traction command targeted to this node.
bool function_policy(NodeHandle src, uint8_t command_byte, uint32_t fnum, uint16_t value, Notifiable *done) override
Applies a policy to function change requests coming in from the OpenLCB bus.
NodeID query_consist(int id, uint8_t *flags) override
Returns the consist target with offset id, or NodeID(0) if there are fewer than id consist targets.
int query_consist_length() override
Returns the number of slaves in this consist.
Train node class with a fixed OpenLCB Node ID.
NodeID node_id() OVERRIDE
NodeID nodeId_
The OpenLCB node ID.
Virtual node class for an OpenLCB train protocol node.
virtual void set_controller(NodeHandle id)=0
virtual bool add_consist(NodeID tgt, uint8_t flags)=0
Adds a node ID to the consist targets.
virtual bool remove_consist(NodeID tgt)=0
Removes a node ID from the consist targets.
virtual NodeHandle get_controller()=0
virtual bool function_policy(NodeHandle src, uint8_t command_byte, uint32_t fnum, uint16_t value, Notifiable *done)=0
Applies a policy to function change requests coming in from the OpenLCB bus.
virtual NodeID query_consist(int id, uint8_t *flags)=0
Fetch a given consist link.
virtual int query_consist_length()=0
virtual void command_hook(NodeHandle src, const Payload &p)=0
Invoked for every incoming traction command targeted to this node.
virtual TrainImpl * train()=0
Collection of control flows necessary for implementing the Traction Protocol.
void unregister_train(TrainNode *node)
Removes a train node from the local interface.
void register_train(TrainNode *node)
Registers a new train with the train service.
Impl * impl_
Implementation flows.
std::unique_ptr< NodeRegistry > nodes_
List of train nodes managed by this Service.
If * iface_
OpenLCB interface.
bool is_known_train_node(Node *node)
Checks if the a given node is a train node operated by this Traction Service.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Definition macros.h:180
uint64_t NodeID
48-bit NMRAnet Node ID type
string Payload
Container that carries the data bytes in an NMRAnet message.
Linked list entry for all registered consist clients for a given train node.
void set_flags(uint8_t new_flags)
Overrides the stored flags.
uint8_t get_flags() const
ConsistEntry(NodeID s, uint8_t flags)
Creates a new consist entry storage.
uint64_t payload
Data contents.
Container of both a NodeID and NodeAlias.
Implementation structure for TrainService.