source: src/mlx/fs.py@ 462:a2c16fb70c27

Last change on this file since 462:a2c16fb70c27 was 408:1e2202fe006b, checked in by István Váradi <ivaradi@…>, 12 years ago

Added support for querying, displaying and simulating the QNH value (re #175)

File size: 12.5 KB
Line 
1
2import const
3from sound import startSound
4
5import fsuipc
6import threading
7import time
8
9#-------------------------------------------------------------------------------
10
11## @package mlx.fs
12#
13# The main interface to the flight simulator.
14#
15# The \ref createSimulator function can be used to create an instance of
16# the class that can be used to access the simulator. It expects an instance of
17# the \ref ConnectionListener class, the member functions of which will be
18# called when something happens with the connection to the simulator.
19#
20# The simulator interface is most often used to retrieve the state of the
21# simulated aircraft. Instances of class \ref AircraftState are used for this
22# purpose.
23#
24# This module also contains some definitions for message sending and implements
25# the timing logic itself.
26
27#-------------------------------------------------------------------------------
28
29class ConnectionListener(object):
30 """Base class for listeners on connections to the flight simulator."""
31 def connected(self, fsType, descriptor):
32 """Called when a connection has been established to the flight
33 simulator of the given type."""
34 print "fs.ConnectionListener.connected, fsType:", fsType, ", descriptor:", descriptor
35
36 def connectionFailed(self):
37 """Called when the connection could not be established."""
38 print "fs.ConnectionListener.connectionFailed"
39
40 def disconnected(self):
41 """Called when a connection to the flight simulator has been broken."""
42 print "fs.ConnectionListener.disconnected"
43
44#-------------------------------------------------------------------------------
45
46class SimulatorException(Exception):
47 """Exception thrown by the simulator interface for communication failure."""
48
49#-------------------------------------------------------------------------------
50
51def createSimulator(type, connectionListener):
52 """Create a simulator instance for the given simulator type with the given
53 connection listener.
54
55 The returned object should provide the following members:
56 FIXME: add info
57 """
58 assert type in [const.SIM_MSFS9, const.SIM_MSFSX], \
59 "Only MS Flight Simulator 2004 and X are supported"
60 return fsuipc.Simulator(connectionListener, connectAttempts = 3)
61
62#-------------------------------------------------------------------------------
63
64class MessageThread(threading.Thread):
65 """Thread to handle messages."""
66 def __init__(self, config, simulator):
67 """Initialize the message thread with the given configuration and
68 simulator."""
69 super(MessageThread, self).__init__()
70
71 self._config = config
72 self._simulator = simulator
73
74 self._requestCondition = threading.Condition()
75 self._messages = []
76 self._nextMessageTime = None
77 self._toQuit = False
78
79 self.daemon = True
80
81 def add(self, messageType, text, duration, disconnect):
82 """Add the given message to the requested messages."""
83 with self._requestCondition:
84 self._messages.append((messageType, text, duration,
85 disconnect))
86 self._requestCondition.notify()
87
88 def quit(self):
89 """Quit the thread."""
90 with self._requestCondition:
91 self._toQuit = True
92 self._requestCondition.notifty()
93 self.join()
94
95 def run(self):
96 """Perform the thread's operation."""
97 while True:
98 (messageType, text, duration, disconnect) = (None, None, None, None)
99 with self._requestCondition:
100 now = time.time()
101 while not self._toQuit and \
102 ((self._nextMessageTime is not None and \
103 self._nextMessageTime>now) or \
104 not self._messages):
105 self._requestCondition.wait(1)
106 now = time.time()
107
108 if self._toQuit: return
109 if self._nextMessageTime is None or \
110 self._nextMessageTime<=now:
111 self._nextMessageTime = None
112
113 if self._messages:
114 (messageType, text,
115 duration, disconnect) = self._messages[0]
116 del self._messages[0]
117
118 if text is not None:
119 self._sendMessage(messageType, text, duration, disconnect)
120
121 def _sendMessage(self, messageType, text, duration, disconnect):
122 """Send the message and setup the next message time."""
123 messageLevel = self._config.getMessageTypeLevel(messageType)
124 if messageLevel==const.MESSAGELEVEL_SOUND or \
125 messageLevel==const.MESSAGELEVEL_BOTH:
126 startSound(const.SOUND_NOTIFY
127 if messageType==const.MESSAGETYPE_VISIBILITY
128 else const.SOUND_DING)
129 if (messageLevel==const.MESSAGELEVEL_FS or \
130 messageLevel==const.MESSAGELEVEL_BOTH):
131 if disconnect:
132 self._simulator.disconnect("[MLX] " + text,
133 duration = duration)
134 else:
135 self._simulator.sendMessage("[MLX] " + text,
136 duration = duration)
137 elif disconnect:
138 self._simulator.disconnect()
139 self._nextMessageTime = time.time() + duration
140
141#-------------------------------------------------------------------------------
142
143_messageThread = None
144
145#-------------------------------------------------------------------------------
146
147def setupMessageSending(config, simulator):
148 """Setup message sending with the given config and simulator."""
149 global _messageThread
150 if _messageThread is not None:
151 _messageThread.quit()
152 _messageThread = MessageThread(config, simulator)
153 _messageThread.start()
154
155#-------------------------------------------------------------------------------
156
157def sendMessage(messageType, text, duration = 3, disconnect = False):
158 """Send the given message of the given type into the simulator and/or play
159 a corresponding sound."""
160 global _messageThread
161 if _messageThread is not None:
162 _messageThread.add(messageType, text, duration, disconnect)
163
164#-------------------------------------------------------------------------------
165
166class AircraftState(object):
167 """Base class for the aircraft state produced by the aircraft model based
168 on readings from the simulator.
169
170 The following data members should be provided at least:
171 - timestamp: the simulator time of the measurement in seconds since the
172 epoch (float)
173 - latitude (in degrees, North is positive)
174 - longitude (in degrees, East is positive)
175 - paused: a boolean indicating if the flight simulator is paused for
176 whatever reason (it could be a pause mode, or a menu, a dialog, or a
177 replay, etc.)
178 - trickMode: a boolean indicating if some "trick" mode (e.g. "SLEW" in
179 MSFS) is activated
180 - overspeed: a boolean indicating if the aircraft is in overspeed
181 - stalled: a boolean indicating if the aircraft is stalled
182 - onTheGround: a boolean indicating if the aircraft is on the ground
183 - zfw: the zero-fuel weight in kilograms (float)
184 - grossWeight: the gross weight in kilograms (float)
185 - heading: the heading of the aircraft in degrees (float)
186 - pitch: the pitch of the aircraft in degrees. Positive means pitch down,
187 negative means pitch up (float)
188 - bank: the bank of the aircraft in degrees. Positive means bank left,
189 negative means bank right (float)
190 - ias: the indicated airspeed in knots (float)
191 - smoothedIAS: the smoothed IAS in knots (float)
192 - mach: the airspeed in mach (float)
193 - groundSpeed: the ground speed (float)
194 - vs: the vertical speed in feet/minutes (float)
195 - smoothedVS: the smoothed VS in feet/minutes (float)
196 - radioAltitude: the radio altitude of the aircraft in feet (float)
197 - altitude: the altitude of the aircraft in feet (float)
198 - gLoad: G-load (float)
199 - flapsSet: the selected degrees of the flaps (float)
200 - flaps: the actual degrees of the flaps (float)
201 - fuel[]: the fuel information. It is a list of tuples with items:
202 the fuel tank identifier and the amount of fuel in that tank in
203 kgs
204 - totalFuel: the total amount of fuel in kg
205 - n1[]: the N1 values of the turbine engines (array of floats
206 of as many items as the number of engines, present only for aircraft with
207 turbines, for other aircraft it is None)
208 - rpm[]: the RPM values of the piston engines (array of floats
209 of as many items as the number of engines, present only for aircraft with
210 pistons, for other aircraft it is None)
211 - reverser[]: an array of booleans indicating if the thrust reversers are
212 activated on any of the engines. The number of items equals to the number
213 of engines with a reverser.
214 - navLightsOn: a boolean indicating if the navigation lights are on. If
215 the detection of the state of the landing lights is unreliable, and should
216 not be considered, this is set to None.
217 - antiCollisionLightsOn: a boolean indicating if the anti-collision lights are on
218 - strobeLightsOn: a boolean indicating if the strobe lights are on
219 - landingLightsOn: a boolean indicating if the landing lights are on. If
220 the detection of the state of the landing lights is unreliable, and should
221 not be considered, this is set to None.
222 - pitotHeatOn: a boolean indicating if the pitot heat is on
223 - parking: a boolean indicating if the parking brake is set
224 - gearControlDown: a boolean indicating if the gear control is set to down
225 - gearsDown: a boolean indicating if the gears are down
226 - spoilersArmed: a boolean indicating if the spoilers have been armed for
227 automatic deployment
228 - spoilersExtension: the percentage of how much the spoiler is extended
229 (float)
230 - altimeter: the altimeter setting in hPa (float)
231 - qnh: the QNH in hPa (float)
232 - altimeterReliable: a boolean indicating if the altimeter setting is
233 reliable
234 - ils: the frequency of the ILS radio in MHz (string). Can be None, if
235 the frequency is unreliable or meaningless.
236 - ols_obs: the OBS setting of the ILS radio in degrees (int). Can be None, if
237 the value is unreliable or meaningless.
238 - ils_manual: a boolean indicating if the ILS radio is on manual control
239 - nav1: the frequency of the NAV1 radio in MHz (string). Can be None, if
240 the frequency is unreliable or meaningless.
241 - nav1_obs: the OBS setting of the NAV1 radio in degrees (int). Can be None, if
242 the value is unreliable or meaningless.
243 - nav1_manual: a boolean indicating if the NAV1 radio is on manual control
244 - nav2: the frequency of the NAV1 radio in MHz (string). Can be None, if
245 the frequency is unreliable or meaningless.
246 - nav2_obs: the OBS setting of the NAV2 radio in degrees (int). Can be None, if
247 the value is unreliable or meaningless.
248 - nav2_manual: a boolean indicating if the NAV2 radio is on manual control
249 - adf1: the frequency of the ADF1 radio in kHz (string). Can be None, if
250 the frequency is unreliable or meaningless.
251 - adf2: the frequency of the ADF2 radio in kHz (string). Can be None, if
252 the frequency is unreliable or meaningless.
253 - squawk: the transponder code (string)
254 - windSpeed: the speed of the wind at the aircraft in knots (float)
255 - windDirection: the direction of the wind at the aircraft in degrees (float)
256 - visibility: the visibility in metres (float)
257 - cog: the centre of gravity
258 - xpdrC: a boolean indicating whether the transponder is in C mode, or
259 None, if the state cannot be read properly
260 - autoXPDR: a boolean indicating whether the transponder is turned on
261 automatically if the aircraft becomes airborne
262 - apMaster: a boolean indicating whether the autopilot is switched on, or
263 None, if the state cannot be read properly
264 - apHeadingHold: a boolean indicating whether the autopilot's heading hold
265 mode is switched on, or None, if the state cannot be read properly
266 - apHeading: the autopilot heading value in degrees (float),
267 or None, if the state cannot be read properly
268 - apAltitudeHold: a boolean indicating whether the autopilot's altitude hold
269 mode is switched on, or None, if the state cannot be read properly
270 - apAltitude: the autopilot altitude value in feet (float),
271 or None, if the state cannot be read properly
272 - elevatorTrim: a float value indicating the deflection of the elevator
273 trim in degrees
274 - antiIceOn: a boolean value indicating if some anti-ice system is turned
275 on. It may be None, if the state of the anti-ice system cannot be read
276 reliably
277 """
Note: See TracBrowser for help on using the repository browser.