FlightGear next
FGInputSocket.cpp
Go to the documentation of this file.
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
28FUNCTIONAL DESCRIPTION
29--------------------------------------------------------------------------------
30This is the place where you create input routines to dump data for perusal
31later.
32
33HISTORY
34--------------------------------------------------------------------------------
3501/20/15 PC Created
36
37%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38INCLUDES
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"
50
51using namespace std;
52
53namespace JSBSim {
54
55/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
56CLASS IMPLEMENTATION
57%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
58
64
65//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66
71
72//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73
75{
76 if (!FGInputType::Load(el))
77 return false;
78
79 SockPort = atoi(el->GetAttributeValue("port").c_str());
80
81 if (SockPort == 0) {
82 cerr << endl << "No port assigned in input element" << endl;
83 return false;
84 }
85
86 string action = el->GetAttributeValue("action");
87 if (to_upper(action) == "BLOCKING_INPUT")
88 BlockingInput = true;
89
90 return true;
91}
92
93//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94
96{
98 delete socket;
100
101 if (socket == 0) return false;
102 if (!socket->GetConnectStatus()) return false;
103
104 return true;
105 }
106
107 return false;
108}
109
110//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
111
112void FGInputSocket::Read(bool Holding)
113{
114 string line, token;
115 size_t start=0, string_start=0, string_end=0;
116 double value=0;
117 FGPropertyNode* node=0;
118
119 if (socket == 0) return;
120 if (!socket->GetConnectStatus()) return;
121
122 if (BlockingInput)
123 socket->WaitUntilReadable(); // block until a transmission is received
124 data = socket->Receive(); // read data
125
126 if (data.size() > 0) {
127 // parse lines
128 while (1) {
129 string_start = data.find_first_not_of("\r\n", start);
130 if (string_start == string::npos) break;
131 string_end = data.find_first_of("\r\n", string_start);
132 if (string_end == string::npos) break;
133 line = data.substr(string_start, string_end-string_start);
134 if (line.size() == 0) break;
135
136 // now parse individual line
137 vector <string> tokens = split(line,' ');
138
139 string command="", argument="", str_value="";
140 if (tokens.size() > 0) {
141 command = to_lower(tokens[0]);
142 if (tokens.size() > 1) {
143 argument = trim(tokens[1]);
144 if (tokens.size() > 2) {
145 str_value = trim(tokens[2]);
146 }
147 }
148 }
149
150 if (command == "set") { // SET PROPERTY
151
152 if (argument.size() == 0) {
153 socket->Reply("No property argument supplied.\n");
154 break;
155 }
156 try {
157 node = PropertyManager->GetNode(argument);
158 } catch(...) {
159 socket->Reply("Badly formed property query\n");
160 break;
161 }
162
163 if (node == 0) {
164 socket->Reply("Unknown property\n");
165 break;
166 } else if (!node->hasValue()) {
167 socket->Reply("Not a leaf property\n");
168 break;
169 } else {
170 value = atof(str_value.c_str());
171 node->setDoubleValue(value);
172 }
173 socket->Reply("set successful\n");
174
175 } else if (command == "get") { // GET PROPERTY
176
177 if (argument.size() == 0) {
178 socket->Reply("No property argument supplied.\n");
179 break;
180 }
181 try {
182 node = PropertyManager->GetNode(argument);
183 } catch(...) {
184 socket->Reply("Badly formed property query\n");
185 break;
186 }
187
188 if (node == 0) {
189 socket->Reply("Unknown property\n");
190 break;
191 } else if (!node->hasValue()) {
192 if (Holding) { // if holding can query property list
193 string query = FDMExec->QueryPropertyCatalog(argument);
194 socket->Reply(query);
195 } else {
196 socket->Reply("Must be in HOLD to search properties\n");
197 }
198 } else {
199 ostringstream buf;
200 buf << argument << " = " << setw(12) << setprecision(6) << node->getDoubleValue() << endl;
201 socket->Reply(buf.str());
202 }
203
204 } else if (command == "hold") { // PAUSE
205
206 FDMExec->Hold();
207 socket->Reply("Holding\n");
208
209 } else if (command == "resume") { // RESUME
210
211 FDMExec->Resume();
212 socket->Reply("Resuming\n");
213
214 } else if (command == "iterate") { // ITERATE
215
216 int argumentInt;
217 istringstream (argument) >> argumentInt;
218 if (argument.size() == 0) {
219 socket->Reply("No argument supplied for number of iterations.\n");
220 break;
221 }
222 if ( !(argumentInt > 0) ){
223 socket->Reply("Required argument must be a positive Integer.\n");
224 break;
225 }
226 FDMExec->EnableIncrementThenHold( argumentInt );
227 FDMExec->Resume();
228 socket->Reply("Iterations performed\n");
229
230 } else if (command == "quit") { // QUIT
231
232 // close the socket connection
233 socket->Reply("Closing connection\n");
234 socket->Close();
235
236 } else if (command == "info") { // INFO
237
238 // get info about the sim run and/or aircraft, etc.
239 ostringstream info;
240 info << "JSBSim version: " << JSBSim_version << endl;
241 info << "Config File version: " << needed_cfg_version << endl;
242 info << "Aircraft simulated: " << FDMExec->GetAircraft()->GetAircraftName() << endl;
243 info << "Simulation time: " << setw(8) << setprecision(3) << FDMExec->GetSimTime() << endl;
244 socket->Reply(info.str());
245
246 } else if (command == "help") { // HELP
247
248 socket->Reply(
249 " JSBSim Server commands:\n\n"
250 " get {property name}\n"
251 " set {property name} {value}\n"
252 " hold\n"
253 " resume\n"
254 " iterate {value}\n"
255 " help\n"
256 " quit\n"
257 " info\n\n");
258
259 } else {
260 socket->Reply(string("Unknown command: ") + token + string("\n"));
261 }
262
263 start = string_end;
264 }
265 }
266
267}
268
269}
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
bool InitModel(void) override
Initializes the instance.
bool Load(Element *el) override
Init the input directives from an XML file.
FGfdmSocket::ProtocolType SockProtocol
void Read(bool Holding) override
Generates the input.
FGInputSocket(FGFDMExec *fdmex)
Constructor.
~FGInputSocket() override
Destructor.
bool Load(Element *el) override
Init the input directives from an XML file (implement the FGModel interface).
bool InitModel(void) override
Init the input model according to its configitation.
FGInputType(FGFDMExec *fdmex)
Constructor (implement the FGModel interface).
static const std::string JSBSim_version
Definition FGJSBBase.h:371
static const std::string needed_cfg_version
Definition FGJSBBase.h:370
FGPropertyManager * PropertyManager
Definition FGModel.h:117
FGFDMExec * FDMExec
Definition FGModel.h:116
Class wrapper for property handling.
Encapsulates an object that enables JSBSim to communicate via socket (input and/or output).
Definition FGfdmSocket.h:71
SGCommandMgr::command_t command
static double atof(const string &str)
Definition options.cxx:107
static int atoi(const string &str)
Definition options.cxx:113
std::string & to_upper(std::string &str)
std::vector< std::string > split(std::string str, char d)
std::string & to_lower(std::string &str)
std::string & trim(std::string &str)