Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
TractionClient.hxx
Go to the documentation of this file.
1
35#ifndef _OPENLCB_TRACTIONCLIENT_HXX_
36#define _OPENLCB_TRACTIONCLIENT_HXX_
37
38#include "openlcb/If.hxx"
39#include "openlcb/Defs.hxx"
40
41namespace openlcb
42{
43
96{
97public:
99 openlcb::Node *local_node)
101 , expectedDst_(local_node)
102 , trigger_(nullptr)
103 , response_(nullptr)
104 {
105 }
106
110 void wait_for_response(NodeHandle target_node, uint8_t expected_type,
111 ::Timer *trigger)
112 {
113 response_ = nullptr;
114 expectedSrc_ = target_node;
115 expectedType_ = expected_type;
116 trigger_ = trigger;
117 start_listening();
118 }
119
122 {
123 return response_;
124 }
125
131 {
132 if (trigger_)
133 {
134 trigger_ = nullptr;
135 stop_listening();
136 }
137 }
138
139private:
140 void start_listening()
141 {
142 iface()->dispatcher()->register_handler(
143 this, openlcb::Defs::MTI_TRACTION_CONTROL_REPLY,
145 }
146
147 void stop_listening()
148 {
149 iface()->dispatcher()->unregister_handler(
150 this, openlcb::Defs::MTI_TRACTION_CONTROL_REPLY,
152 }
153
155 {
156 LOG(VERBOSE, "response came");
157
158 if (!trigger_)
159 {
160 // We already matched -- drop all packets to the floor.
161 LOG(VERBOSE, "no trigger");
162 return release_and_exit();
163 }
164 if (nmsg()->dstNode != expectedDst_) {
165 LOG(VERBOSE, "dst not match");
166 return release_and_exit();
167 }
171 if (expectedSrc_.id && nmsg()->src.id)
172 {
173 if (expectedSrc_.id != nmsg()->src.id)
174 {
175 LOG(VERBOSE, "src.id not match");
176 return release_and_exit();
177 }
178 }
179 else if (expectedSrc_.alias && nmsg()->src.alias)
180 {
181 if (expectedSrc_.alias != nmsg()->src.alias)
182 {
183 LOG(VERBOSE, "src.alias not match");
184 return release_and_exit();
185 }
186 }
187 else
188 {
191 DIE("Unable to decide whether the incoming response is coming from "
192 "the right place.");
193 }
194 // Now: message is from the right source node, to the right destination
195 // node.
196 if (nmsg()->payload.size() < 1) {
197 LOG(VERBOSE, "no payload");
198 return release_and_exit();
199 }
200 if (nmsg()->payload[0] != expectedType_) {
201 LOG(VERBOSE, "payload type no match");
202 return release_and_exit();
203 }
204 // Now: we matched!
205 stop_listening();
206 response_ = transfer_message();
207 trigger_->trigger();
208 trigger_ = nullptr;
209 return exit();
210 }
211
212 openlcb::NodeHandle expectedSrc_;
213 openlcb::Node *expectedDst_;
214 // First byte of the response message.
215 uint8_t expectedType_;
216 ::Timer *trigger_;
217 Buffer<GenMessage> *response_;
218};
219
220} // namespace openlcb
221
222#endif // _OPENLCB_TRACTIONCLIENT_HXX_
Base class for all QMember types that hold data in an expandable format.
Definition Buffer.hxx:195
void register_handler(HandlerType *handler, ID id, ID mask)
Adds a new handler to this dispatcher.
void unregister_handler(HandlerType *handler, ID id, ID mask)
Removes a specific instance of a handler from this dispatcher.
A timer that can schedule itself to run on an executor at specified times in the future.
Definition Timer.hxx:134
void trigger()
This will wakeup the timer prematurely, immediately.
Definition Timer.hxx:237
Base::Action Action
Allows using Action without having StateFlowBase:: prefix in front of it.
MessageType * transfer_message()
Releases ownership of the current message.
Abstract class representing an OpenLCB Interface.
Definition If.hxx:185
MessageDispatchFlow * dispatcher()
Definition If.hxx:224
Base class for incoming message handler flows.
Definition If.hxx:400
GenMessage * nmsg()
Returns the NMRAnet message we received.
Definition If.hxx:413
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
This class helps waiting for traction responses.
Action entry() OVERRIDE
Entry into the StateFlow activity.
void wait_for_response(NodeHandle target_node, uint8_t expected_type, ::Timer *trigger)
Starts waiting for a traction control reply from a given node with the first byte 'expected_type'.
void wait_timeout()
Call this if the timeout has expired.
Buffer< GenMessage > * response()
Caller must unref this buffer when done with it.
#define LOG(level, message...)
Conditionally write a message to the logging output.
Definition logging.h:99
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
Definition logging.h:59
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Definition macros.h:180
#define DIE(MSG)
Unconditionally terminates the current process with a message.
Definition macros.h:143
@ MTI_EXACT
match mask for a single MTI
Container of both a NodeID and NodeAlias.
NodeID id
48-bit NMRAnet Node ID
NodeAlias alias
alias to NMRAnet Node ID