Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Server.cxx
Go to the documentation of this file.
1
28#include "withrottle/Server.hxx"
29
30namespace withrottle
31{
32
39 : StateFlowBase(server)
40 , olcbThrottle(node)
41 , server(server)
42 , fd(fd)
43 , data()
44 , dataIndex(0)
45 , state(STATE_COMMAND)
46 , selectHelper(this)
47 , dispatcher(server)
48 , command(dispatcher.alloc())
49 , serverCommandLoco(this)
50{
51}
52
53/*
54 * ThrottleFlow::entry()
55 */
63
64/*
65 * ThrottleFlow::data_sent()
66 */
72
73/*
74 * ThrottleFlow::data_received()
75 */
77{
79 {
80 /* remote throttle has closed the connection */
81 printf("WiThrottle connection closed\n");
82 return delete_this();
83 }
84
85 //printf("WiThrottle strraw: %.*s\n",
86 // sizeof(readRaw) - selectHelper.remaining_, readRaw);
87
88 data.append(readRaw, sizeof(readRaw) - selectHelper.remaining_);
89 if (data.find('\n' != string::npos))
90 {
91 bool result;
92 do
93 {
94 result = parse();
95 if (result)
96 {
99 }
100 } while (result);
101 }
102
103 return read_single(&selectHelper, fd, readRaw, sizeof(readRaw),
105}
106
107/*
108 * ThrottleFlow::parse()
109 */
111{
112 const char *c_str = data.c_str();
113 printf("WiThrottle stream: %s\n", c_str + dataIndex);
114
115 do
116 {
117 switch (state)
118 {
119 case STATE_COMMAND:
120 if (data.length() < 2)
121 {
122 /* need more data first */
123 return false;
124 }
126 break;
127 case STATE_MULTI_TYPE:
129 break;
130 case STATE_TRAIN:
131 parse_train();
132 break;
133 case STATE_SUBCOMMAND:
134 if (parse_subcommand())
135 {
136 return true;
137 }
138 break;
139 case STATE_PAYLOAD:
140 default:
141 case STATE_NEXT:
142 if (data[0] == '\n')
143 {
144 dataIndex = 0;
146 }
147 data.erase(0, 1);
148 break;
149 }
150 } while (data.length());
151
152 return false;
153}
154
155/*
156 * ThrottleFlow::parse_command()
157 */
159{
160 command->data()->commandType = (CommandType)data[0];
161
162 switch (data[0])
163 {
164 default:
165 case SECONDARY:
166 case HEX_PACKET:
167 case PANEL:
168 case ROSTER:
169 case QUIT:
171 return;
172 case MULTI:
173 state = data[1] == 'T' ? STATE_MULTI_TYPE : STATE_NEXT;
174 data.erase(0, 1);
175 break;
176 case PRIMARY:
178 break;
179 case HEARTBEAT:
180 case SET_NAME:
181 write(fd, "*10\n\n", 5);
182 case SET_ID:
184 break;
185 }
186
187 data.erase(0, 1);
188}
189
190/*
191 * ThrottleFlow::parse_multi_type()
192 */
194{
195 switch (data[0])
196 {
197 default:
199 return;
200 case ACTION:
201 case ADD:
202 case REMOVE:
204 command->data()->commandMultiType = (CommandMultiType)data[0];
205 break;
206 }
207
208 data.erase(0, 1);
209}
210
211/*
212 * ThrottleFlow::parse_train()
213 */
215{
216 size_t end = data.find("<;>");
217
218 switch (end)
219 {
220 case string::npos:
221 case 1:
222 if (data[0] == '*')
223 {
224 break;
225 }
226 case 0:
227 /* invalid string */
229 return;
230 }
231
232 command->data()->train.assign(data, 0, end);
233 data.erase(0, end + 3);
235}
236
237/*
238 * ThrottleFlow::parse_subcommand()
239 */
241{
242 switch (data[0])
243 {
244 default:
245 case VELOCITY:
246 case ESTOP:
247 case FUNCTION:
248 case FORCE:
249 case DIRECTION:
250 case RELEASE:
251 case DISPATCH:
252 case ADDR_SHORT:
253 case ADDR_ROSTER:
254 case CONSIST:
255 case CONSIST_LEAD:
256 case IDLE:
257 case SS_MODE:
258 case MOMENTARY:
259 case QUERY:
261 return false;
262 case ADDR_LONG:
264 break;
265 }
266
267 command->data()->commandSubType = (CommandSubType)data[0];
268 data.erase(0, 1);
269
270 size_t end = data.find('\n');
271
272 switch (end)
273 {
274 case string::npos:
275 /* invalid payload */
277 return false;
278 }
279
280 command->data()->payload.assign(data, 0, end);
281 data.erase(0, end);
283 return true;
284}
285
286} /* namespace withrottle */
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
Definition StateFlow.hxx:61
MessageType * alloc()
Synchronously allocates a message buffer from the pool of this flow.
void init()
Initiailize a QMember, in place of a public placement construction.
Definition QMember.hxx:46
Return type for a state flow callback.
Base class for state machines.
Action read_single(StateFlowSelectHelper *helper, int fd, void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO)
Attempts to read at most size_t bytes, and blocks the caller until at least one byte is read.
Action delete_this()
Terminates the flow and deletes *this.
Action write_repeated(StateFlowSelectHelper *helper, int fd, const void *buf, size_t size, Callback c, unsigned priority=Selectable::MAX_PRIO)
Writes some data into a file descriptor, repeating the operation as necessary until all bytes are wri...
void send(MessageType *msg, unsigned priority=UINT_MAX) OVERRIDE
Sends a message to the state flow for processing.
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
WiThrottle server object.
Definition Server.hxx:50
StateFlowBase::Action data_sent()
Data sent successfully.
Definition Server.cxx:67
string data
agrigate pre-processed stream data
Definition Server.hxx:184
CommandDispatchFlow dispatcher
flow responsible for routing incoming messages to handlers.
Definition Server.hxx:199
void parse_multi_type()
Parse the incoming data.
Definition Server.cxx:193
void parse_command()
Parse the incoming data.
Definition Server.cxx:158
StateFlowBase::Action data_received()
Process read data.
Definition Server.cxx:76
StateFlowSelectHelper selectHelper
Helper for waiting on data from a file descriptor.
Definition Server.hxx:193
ThrottleFlow(Server *server, int fd, openlcb::Node *node)
Constructor.
Definition Server.cxx:38
bool parse()
Parse the incoming data.
Definition Server.cxx:110
void parse_train()
Parse the incoming data.
Definition Server.cxx:214
ServerState state
Current state of parsing the data.
Definition Server.hxx:190
size_t dataIndex
data index for parsing
Definition Server.hxx:187
int fd
socket descriptor of throttle connection
Definition Server.hxx:178
bool parse_subcommand()
Parse the incoming data.
Definition Server.cxx:240
Buffer< ThrottleCommand > * command
throttle command
Definition Server.hxx:202
char readRaw[128]
read data buffer
Definition Server.hxx:181
StateFlowBase::Action entry()
Beginning of state flow.
Definition Server.cxx:56
unsigned remaining_
Number of bytes still outstanding to read.
unsigned hasError_
1 if there was an error reading of writing.
static string get_init_string()
Get the init command string.
CommandType
type of command.
@ SET_ID
set the device id
@ SET_NAME
set the device name
@ SECONDARY
secondary throttle
@ HEARTBEAT
send hardbeat or set heartbeat on/off
@ QUIT
device has quit
@ HEX_PACKET
hex packet for command station
@ MULTI
multi throttle
@ PANEL
send panel command
@ ROSTER
send roster command
@ PRIMARY
primary throttle
CommandSubType
type of throttle command.
@ DIRECTION
set direction
@ ADDR_ROSTER
set address from roster entry
@ QUERY
query about current speed, direction, etc...
@ IDLE
idle, set speed to 0
@ SS_MODE
set speed step mode
@ VELOCITY
velocity command
@ CONSIST_LEAD
consist lead from roster entry
@ ADDR_LONG
set long address
@ ADDR_SHORT
set short address
@ DISPATCH
dispatch a loco
@ MOMENTARY
momentary
@ FORCE
force function
@ FUNCTION
function key
@ RELEASE
release a loco
CommandMultiType
type of multi throttle command.
@ REMOVE
remove a locomotive from the throttle
@ ADD
Add a locomotive to the throttle.
@ ACTION
pefrom an action
@ STATE_SUBCOMMAND
look for sub-command
@ STATE_MULTI_TYPE
look for the multi-throttle type
@ STATE_COMMAND
look for command
@ STATE_TRAIN
look for the train
@ STATE_PAYLOAD
look for data
@ STATE_NEXT
look for next command