]> git.mxchange.org Git - flightgear.git/blob - src/FDM/ExternalNet/ExternalNet.cxx
PLIB net removed from FlightGear
[flightgear.git] / src / FDM / ExternalNet / ExternalNet.cxx
1 // ExternalNet.hxx -- an net interface to an external flight dynamics model
2 //
3 // Written by Curtis Olson, started November 2001.
4 //
5 // Copyright (C) 2001  Curtis L. Olson  - http://www.flightgear.org/~curt
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <simgear/debug/logstream.hxx>
28 #include <simgear/io/lowlevel.hxx> // endian tests
29 #include <simgear/io/sg_netBuffer.hxx>
30
31 #include <Main/fg_props.hxx>
32 #include <Network/native_ctrls.hxx>
33 #include <Network/native_fdm.hxx>
34
35 #include "ExternalNet.hxx"
36
37
38 class HTTPClient : public simgear::NetBufferChannel
39 {
40
41     bool done;
42     SGTimeStamp start;
43
44 public:
45
46     HTTPClient ( const char* host, int port, const char* path ) :
47         done( false )
48     {
49         open ();
50         connect (host, port);
51
52   char buffer[256];
53   ::snprintf (buffer, 256, "GET %s HTTP/1.0\r\n\r\n", path );
54         bufferSend(buffer, strlen(buffer) ) ;
55
56         start.stamp();
57     }
58
59     virtual void handleBufferRead (simgear::NetBuffer& buffer)
60     {
61         const char* s = buffer.getData();
62         while (*s)
63             fputc(*s++,stdout);
64
65         printf("done\n");
66         buffer.remove();
67         printf("after buffer.remove()\n");
68         done = true;
69     }
70
71     bool isDone() const { return done; }
72     bool isDone( long usec ) const { 
73         if ( start + SGTimeStamp::fromUSec(usec) < SGTimeStamp::now() ) {
74             return true;
75         } else {
76             return done;
77         }
78     }
79 };
80
81 FGExternalNet::FGExternalNet( double dt, string host, int dop, int dip, int cp )
82 {
83 //     set_delta_t( dt );
84
85     valid = true;
86
87     data_in_port = dip;
88     data_out_port = dop;
89     cmd_port = cp;
90     fdm_host = host;
91
92     /////////////////////////////////////////////////////////
93     // Setup client udp connection (sends data to remote fdm)
94
95     if ( ! data_client.open( false ) ) {
96         SG_LOG( SG_FLIGHT, SG_ALERT, "Error opening client data channel" );
97         valid = false;
98     }
99
100     // fire and forget
101     data_client.setBlocking( false );
102
103     if ( data_client.connect( fdm_host.c_str(), data_out_port ) == -1 ) {
104         printf("error connecting to %s:%d\n", fdm_host.c_str(), data_out_port);
105         valid = false;
106     }
107
108     /////////////////////////////////////////////////////////
109     // Setup server udp connection (for receiving data)
110
111     if ( ! data_server.open( false ) ) {
112         SG_LOG( SG_FLIGHT, SG_ALERT, "Error opening client server channel" );
113         valid = false;
114     }
115
116     // disable blocking
117     data_server.setBlocking( false );
118
119     // allowed to read from a broadcast addr
120     // data_server.setBroadcast( true );
121
122     // if we bind to fdm_host = "" then we accept messages from
123     // anyone.
124     if ( data_server.bind( "", data_in_port ) == -1 ) {
125         printf("error binding to port %d\n", data_in_port);
126         valid = false;
127     }
128 }
129
130
131 FGExternalNet::~FGExternalNet() {
132     data_client.close();
133     data_server.close();
134 }
135
136
137 // Initialize the ExternalNet flight model, dt is the time increment
138 // for each subsequent iteration through the EOM
139 void FGExternalNet::init() {
140     // cout << "FGExternalNet::init()" << endl;
141
142     // Explicitly call the superclass's
143     // init method first.
144     common_init();
145
146     double lon = fgGetDouble( "/sim/presets/longitude-deg" );
147     double lat = fgGetDouble( "/sim/presets/latitude-deg" );
148     double alt = fgGetDouble( "/sim/presets/altitude-ft" );
149     double ground = get_Runway_altitude_m();
150     double heading = fgGetDouble("/sim/presets/heading-deg");
151     double speed = fgGetDouble( "/sim/presets/airspeed-kt" );
152
153     char cmd[256];
154
155     HTTPClient *http;
156     sprintf( cmd, "/longitude-deg?value=%.8f", lon );
157     http = new HTTPClient( fdm_host.c_str(), cmd_port, cmd );
158     while ( !http->isDone(1000000) ) http->poll(0);
159     delete http;
160
161     sprintf( cmd, "/latitude-deg?value=%.8f", lat );
162     http = new HTTPClient( fdm_host.c_str(), cmd_port, cmd );
163     while ( !http->isDone(1000000) ) http->poll(0);
164     delete http;
165
166     sprintf( cmd, "/altitude-ft?value=%.8f", alt );
167     http = new HTTPClient( fdm_host.c_str(), cmd_port, cmd );
168     while ( !http->isDone(1000000) ) http->poll(0);
169     delete http;
170
171     sprintf( cmd, "/ground-m?value=%.8f", ground );
172     http = new HTTPClient( fdm_host.c_str(), cmd_port, cmd );
173     while ( !http->isDone(1000000) ) http->poll(0);
174     delete http;
175
176     sprintf( cmd, "/speed-kts?value=%.8f", speed );
177     http = new HTTPClient( fdm_host.c_str(), cmd_port, cmd );
178     while ( !http->isDone(1000000) ) http->poll(0);
179     delete http;
180
181     sprintf( cmd, "/heading-deg?value=%.8f", heading );
182     http = new HTTPClient( fdm_host.c_str(), cmd_port, cmd );
183     while ( !http->isDone(1000000) ) http->poll(0);
184     delete http;
185
186     SG_LOG( SG_IO, SG_INFO, "before sending reset command." );
187
188     if( fgGetBool("/sim/presets/onground") ) {
189       sprintf( cmd, "/reset?value=ground" );
190     } else {
191       sprintf( cmd, "/reset?value=air" );
192     }
193     http = new HTTPClient( fdm_host.c_str(), cmd_port, cmd );
194     while ( !http->isDone(1000000) ) http->poll(0);
195     delete http;
196
197     SG_LOG( SG_IO, SG_INFO, "Remote FDM init() finished." );
198 }
199
200
201 // Run an iteration of the EOM.
202 void FGExternalNet::update( double dt ) {
203     int length;
204     int result;
205
206     if (is_suspended())
207       return;
208
209     // Send control positions to remote fdm
210     length = sizeof(ctrls);
211     FGProps2NetCtrls( &ctrls, true, true );
212     if ( data_client.send( (char *)(& ctrls), length, 0 ) != length ) {
213         SG_LOG( SG_IO, SG_DEBUG, "Error writing data." );
214     } else {
215         SG_LOG( SG_IO, SG_DEBUG, "wrote control data." );
216     }
217
218     // Read next set of FDM data (blocking enabled to maintain 'sync')
219     length = sizeof(fdm);
220     while ( (result = data_server.recv( (char *)(& fdm), length, 0)) >= 0 ) {
221         SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
222         FGNetFDM2Props( &fdm );
223     }
224 }