JSBSim Flight Dynamics Model  1.0 (02 March 2017)
An Open Source Flight Dynamics and Control Software Library in C++
FGInputSocket.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 
3  Module: FGInputSocket.cpp
4  Author: Paul Chavent
5  Date started: 01/20/15
6  Purpose: Manage input of sim parameters to a socket
7  Called by: FGInput
8 
9  ------------- Copyright (C) 2015 Paul Chavent -------------
10 
11  This program is free software; you can redistribute it and/or modify it under
12  the terms of the GNU Lesser General Public License as published by the Free Software
13  Foundation; either version 2 of the License, or (at your option) any later
14  version.
15 
16  This program is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19  details.
20 
21  You should have received a copy of the GNU Lesser General Public License along with
22  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
23  Place - Suite 330, Boston, MA 02111-1307, USA.
24 
25  Further information about the GNU Lesser General Public License can also be found on
26  the world wide web at http://www.gnu.org.
27 
28 FUNCTIONAL DESCRIPTION
29 --------------------------------------------------------------------------------
30 This is the place where you create input routines to dump data for perusal
31 later.
32 
33 HISTORY
34 --------------------------------------------------------------------------------
35 01/20/15 PC Created
36 
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 INCLUDES
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
40 
41 #include <cstring>
42 #include <cstdlib>
43 #include <sstream>
44 #include <iomanip>
45 
46 #include "FGInputSocket.h"
47 #include "FGFDMExec.h"
48 #include "models/FGAircraft.h"
49 #include "input_output/FGXMLElement.h"
50 
51 using namespace std;
52 
53 namespace JSBSim {
54 
55 IDENT(IdSrc,"$Id");
56 IDENT(IdHdr,ID_INPUTSOCKET);
57 
58 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 CLASS IMPLEMENTATION
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
61 
62 FGInputSocket::FGInputSocket(FGFDMExec* fdmex) :
63  FGInputType(fdmex),
64  socket(0)
65 {
66 }
67 
68 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
69 
71 {
72  delete socket;
73 }
74 
75 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 
78 {
79  if (!FGInputType::Load(el))
80  return false;
81 
82  SockPort = atoi(el->GetAttributeValue("port").c_str());
83 
84  if (SockPort == 0) {
85  cerr << endl << "No port assigned in input element" << endl;
86  return false;
87  }
88 
89  return true;
90 }
91 
92 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 
95 {
96  if (FGInputType::InitModel()) {
97  delete socket;
98  socket = new FGfdmSocket(SockPort);
99 
100  if (socket == 0) return false;
101  if (!socket->GetConnectStatus()) return false;
102 
103  return true;
104  }
105 
106  return false;
107 }
108 
109 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 
111 void FGInputSocket::Read(bool Holding)
112 {
113  string line, token;
114  size_t start=0, string_start=0, string_end=0;
115  double value=0;
116  FGPropertyNode* node=0;
117 
118  if (socket == 0) return;
119  if (!socket->GetConnectStatus()) return;
120 
121  data = socket->Receive(); // get socket transmission if present
122 
123  if (data.size() > 0) {
124  // parse lines
125  while (1) {
126  string_start = data.find_first_not_of("\r\n", start);
127  if (string_start == string::npos) break;
128  string_end = data.find_first_of("\r\n", string_start);
129  if (string_end == string::npos) break;
130  line = data.substr(string_start, string_end-string_start);
131  if (line.size() == 0) break;
132 
133  // now parse individual line
134  vector <string> tokens = split(line,' ');
135 
136  string command="", argument="", str_value="";
137  if (tokens.size() > 0) {
138  command = to_lower(tokens[0]);
139  if (tokens.size() > 1) {
140  argument = trim(tokens[1]);
141  if (tokens.size() > 2) {
142  str_value = trim(tokens[2]);
143  }
144  }
145  }
146 
147  if (command == "set") { // SET PROPERTY
148 
149  if (argument.size() == 0) {
150  socket->Reply("No property argument supplied.\n");
151  break;
152  }
153  try {
154  node = PropertyManager->GetNode(argument);
155  } catch(...) {
156  socket->Reply("Badly formed property query\n");
157  break;
158  }
159 
160  if (node == 0) {
161  socket->Reply("Unknown property\n");
162  break;
163  } else if (!node->hasValue()) {
164  socket->Reply("Not a leaf property\n");
165  break;
166  } else {
167  value = atof(str_value.c_str());
168  node->setDoubleValue(value);
169  }
170  socket->Reply("");
171 
172  } else if (command == "get") { // GET PROPERTY
173 
174  if (argument.size() == 0) {
175  socket->Reply("No property argument supplied.\n");
176  break;
177  }
178  try {
179  node = PropertyManager->GetNode(argument);
180  } catch(...) {
181  socket->Reply("Badly formed property query\n");
182  break;
183  }
184 
185  if (node == 0) {
186  socket->Reply("Unknown property\n");
187  break;
188  } else if (!node->hasValue()) {
189  if (Holding) { // if holding can query property list
190  string query = FDMExec->QueryPropertyCatalog(argument);
191  socket->Reply(query);
192  } else {
193  socket->Reply("Must be in HOLD to search properties\n");
194  }
195  } else {
196  ostringstream buf;
197  buf << argument << " = " << setw(12) << setprecision(6) << node->getDoubleValue() << endl;
198  socket->Reply(buf.str());
199  }
200 
201  } else if (command == "hold") { // PAUSE
202 
203  FDMExec->Hold();
204  socket->Reply("");
205 
206  } else if (command == "resume") { // RESUME
207 
208  FDMExec->Resume();
209  socket->Reply("");
210 
211  } else if (command == "iterate") { // ITERATE
212 
213  int argumentInt;
214  istringstream (argument) >> argumentInt;
215  if (argument.size() == 0) {
216  socket->Reply("No argument supplied for number of iterations.\n");
217  break;
218  }
219  if ( !(argumentInt > 0) ){
220  socket->Reply("Required argument must be a positive Integer.\n");
221  break;
222  }
223  FDMExec->EnableIncrementThenHold( argumentInt );
224  FDMExec->Resume();
225  socket->Reply("");
226 
227  } else if (command == "quit") { // QUIT
228 
229  // close the socket connection
230  socket->Reply("");
231  socket->Close();
232 
233  } else if (command == "info") { // INFO
234 
235  // get info about the sim run and/or aircraft, etc.
236  ostringstream info;
237  info << "JSBSim version: " << JSBSim_version << endl;
238  info << "Config File version: " << needed_cfg_version << endl;
239  info << "Aircraft simulated: " << FDMExec->GetAircraft()->GetAircraftName() << endl;
240  info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl;
241  socket->Reply(info.str());
242 
243  } else if (command == "help") { // HELP
244 
245  socket->Reply(
246  " JSBSim Server commands:\n\n"
247  " get {property name}\n"
248  " set {property name} {value}\n"
249  " hold\n"
250  " resume\n"
251  " iterate {value}\n"
252  " help\n"
253  " quit\n"
254  " info\n\n");
255 
256  } else {
257  socket->Reply(string("Unknown command: ") + token + string("\n"));
258  }
259 
260  start = string_end;
261  }
262  }
263 
264 }
265 
266 }
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
virtual bool Load(Element *el)
Init the input directives from an XML file (implement the FGModel interface).
Definition: FGInputType.cpp:81
Class wrapper for property handling.
const std::string & GetAircraftName(void) const
Gets the aircraft name.
Definition: FGAircraft.h:139
STL namespace.
Abstract class to provide functions generic to all the input directives.
Definition: FGInputType.h:79
void Hold(void)
Pauses execution by preventing time from incrementing.
Definition: FGFDMExec.h:478
FGAircraft * GetAircraft(void)
Returns the FGAircraft pointer.
Definition: FGFDMExec.h:367
void EnableIncrementThenHold(int Timesteps)
Turn on hold after increment.
Definition: FGFDMExec.h:480
bool InitModel(void)
Initializes the instance.
~FGInputSocket()
Destructor.
std::string QueryPropertyCatalog(const std::string &check)
Retrieves property or properties matching the supplied string.
Definition: FGFDMExec.cpp:932
double GetSimTime(void) const
Returns the cumulative simulation time in seconds.
Definition: FGFDMExec.h:533
void Resume(void)
Resumes execution from a "Hold".
Definition: FGFDMExec.h:484
void Read(bool Holding)
Generates the input.
bool Load(Element *el)
Init the input directives from an XML file.
virtual bool InitModel(void)
Init the input model according to its configitation.
Definition: FGInputType.cpp:97
Encapsulates the JSBSim simulation executive.
Definition: FGFDMExec.h:189
Encapsulates an object that enables JSBSim to communicate via socket (input and/or output)...
Definition: FGfdmSocket.h:89