source: src/mlx/fs.py@ 164:a2bd429c9f9e

Last change on this file since 164:a2bd429c9f9e was 152:f0701a18628a, checked in by István Váradi <ivaradi@…>, 13 years ago

Made the sending of the closing message more reliable

File size: 9.1 KB
Line 
1# Module for generic flight-simulator interfaces
2
3#-------------------------------------------------------------------------------
4
5import const
6from sound import startSound
7
8import fsuipc
9import threading
10import time
11
12#-------------------------------------------------------------------------------
13
14class ConnectionListener(object):
15 """Base class for listeners on connections to the flight simulator."""
16 def connected(self, fsType, descriptor):
17 """Called when a connection has been established to the flight
18 simulator of the given type."""
19 print "fs.ConnectionListener.connected, fsType:", fsType, ", descriptor:", descriptor
20
21 def connectionFailed(self):
22 """Called when the connection could not be established."""
23 print "fs.ConnectionListener.connectionFailed"
24
25 def disconnected(self):
26 """Called when a connection to the flight simulator has been broken."""
27 print "fs.ConnectionListener.disconnected"
28
29#-------------------------------------------------------------------------------
30
31class SimulatorException(Exception):
32 """Exception thrown by the simulator interface for communication failure."""
33
34#-------------------------------------------------------------------------------
35
36def createSimulator(type, connectionListener):
37 """Create a simulator instance for the given simulator type with the given
38 connection listener.
39
40 The returned object should provide the following members:
41 FIXME: add info
42 """
43 assert type in [const.SIM_MSFS9, const.SIM_MSFSX], \
44 "Only MS Flight Simulator 2004 and X are supported"
45 return fsuipc.Simulator(connectionListener, connectAttempts = 3)
46
47#-------------------------------------------------------------------------------
48
49class MessageThread(threading.Thread):
50 """Thread to handle messages."""
51 def __init__(self, config, simulator):
52 """Initialize the message thread with the given configuration and
53 simulator."""
54 super(MessageThread, self).__init__()
55
56 self._config = config
57 self._simulator = simulator
58
59 self._requestCondition = threading.Condition()
60 self._messages = []
61 self._nextMessageTime = None
62 self._toQuit = False
63
64 self.daemon = True
65
66 def add(self, messageType, text, duration, disconnect):
67 """Add the given message to the requested messages."""
68 with self._requestCondition:
69 self._messages.append((messageType, text, duration,
70 disconnect))
71 self._requestCondition.notify()
72
73 def quit(self):
74 """Quit the thread."""
75 with self._requestCondition:
76 self._toQuit = True
77 self._requestCondition.notifty()
78 self.join()
79
80 def run(self):
81 """Perform the thread's operation."""
82 while True:
83 (messageType, text, duration, disconnect) = (None, None, None, None)
84 with self._requestCondition:
85 now = time.time()
86 while not self._toQuit and \
87 ((self._nextMessageTime is not None and \
88 self._nextMessageTime>now) or \
89 not self._messages):
90 self._requestCondition.wait(1)
91 now = time.time()
92
93 if self._toQuit: return
94 if self._nextMessageTime is None or \
95 self._nextMessageTime<=now:
96 self._nextMessageTime = None
97
98 if self._messages:
99 (messageType, text,
100 duration, disconnect) = self._messages[0]
101 del self._messages[0]
102
103 if text is not None:
104 self._sendMessage(messageType, text, duration, disconnect)
105
106 def _sendMessage(self, messageType, text, duration, disconnect):
107 """Send the message and setup the next message time."""
108 messageLevel = self._config.getMessageTypeLevel(messageType)
109 if messageLevel==const.MESSAGELEVEL_SOUND or \
110 messageLevel==const.MESSAGELEVEL_BOTH:
111 startSound(const.SOUND_DING)
112 if (messageLevel==const.MESSAGELEVEL_FS or \
113 messageLevel==const.MESSAGELEVEL_BOTH):
114 if disconnect:
115 self._simulator.disconnect("[MLX] " + text,
116 duration = duration)
117 else:
118 self._simulator.sendMessage("[MLX] " + text,
119 duration = duration)
120 elif disconnecte:
121 self._simulator.disconnect()
122 self._nextMessageTime = time.time() + duration
123
124#-------------------------------------------------------------------------------
125
126_messageThread = None
127
128#-------------------------------------------------------------------------------
129
130def setupMessageSending(config, simulator):
131 """Setup message sending with the given config and simulator."""
132 global _messageThread
133 if _messageThread is not None:
134 _messageThread.quit()
135 _messageThread = MessageThread(config, simulator)
136 _messageThread.start()
137
138#-------------------------------------------------------------------------------
139
140def sendMessage(messageType, text, duration = 3, disconnect = False):
141 """Send the given message of the given type into the simulator and/or play
142 a corresponding sound."""
143 global _messageThread
144 if _messageThread is not None:
145 _messageThread.add(messageType, text, duration, disconnect)
146
147#-------------------------------------------------------------------------------
148
149class AircraftState(object):
150 """Base class for the aircraft state produced by the aircraft model based
151 on readings from the simulator.
152
153 The following data members should be provided at least:
154 - timestamp: the simulator time of the measurement in seconds since the
155 epoch (float)
156 - latitude (in degrees, North is positive)
157 - longitude (in degrees, East is positive)
158 - paused: a boolean indicating if the flight simulator is paused for
159 whatever reason (it could be a pause mode, or a menu, a dialog, or a
160 replay, etc.)
161 - trickMode: a boolean indicating if some "trick" mode (e.g. "SLEW" in
162 MSFS) is activated
163 - overspeed: a boolean indicating if the aircraft is in overspeed
164 - stalled: a boolean indicating if the aircraft is stalled
165 - onTheGround: a boolean indicating if the aircraft is on the ground
166 - zfw: the zero-fuel weight in kilograms (float)
167 - grossWeight: the gross weight in kilograms (float)
168 - heading: the heading of the aircraft in degrees (float)
169 - pitch: the pitch of the aircraft in degrees. Positive means pitch down,
170 negative means pitch up (float)
171 - bank: the bank of the aircraft in degrees. Positive means bank left,
172 negative means bank right (float)
173 - ias: the indicated airspeed in knots (float)
174 - mach: the airspeed in mach (float)
175 - groundSpeed: the ground speed (float)
176 - vs: the vertical speed in feet/minutes (float)
177 - radioAltitude: the radio altitude of the aircraft in feet (float)
178 - altitude: the altitude of the aircraft in feet (float)
179 - gLoad: G-load (float)
180 - flapsSet: the selected degrees of the flaps (float)
181 - flaps: the actual degrees of the flaps (float)
182 - fuelWeight[]: the fuel weights in the different tanks in kgs (array of
183 floats of as many items as the number fuel tanks)
184 - n1[]: the N1 values of the turbine engines (array of floats
185 of as many items as the number of engines, present only for aircraft with
186 turbines)
187 - rpm[]: the RPM values of the piston engines (array of floats
188 of as many items as the number of engines, present only for aircraft with
189 pistons)
190 - reverser[]: an array of booleans indicating if the thrust reversers are
191 activated on any of the engines. The number of items equals to the number
192 of engines with a reverser.
193 - navLightsOn: a boolean indicating if the navigation lights are on
194 - antiCollisionLightsOn: a boolean indicating if the anti-collision lights are on
195 - strobeLightsOn: a boolean indicating if the strobe lights are on
196 - landingLightsOn: a boolean indicating if the landing lights are on
197 - pitotHeatOn: a boolean indicating if the pitot heat is on
198 - parking: a boolean indicating if the parking brake is set
199 - gearsDown: a boolean indicating if the gears are down
200 - spoilersArmed: a boolean indicating if the spoilers have been armed for
201 automatic deployment
202 - spoilersExtension: the percentage of how much the spoiler is extended
203 (float)
204 - altimeter: the altimeter setting in hPa (float)
205 - nav1: the frequency of the NAV1 radio in MHz (string)
206 - nav2: the frequency of the NAV1 radio in MHz (string)
207 - squawk: the transponder code (string)
208 - windSpeed: the speed of the wind at the aircraft in knots (float)
209 - windDirection: the direction of the wind at the aircraft in degrees (float)
210 - visibility: the visibility in metres (float)
211
212 FIXME: needed when taxiing only:
213 - payload weight
214
215 FIXME: needed rarely:
216 - latitude, longitude
217 - transporter
218 - visibility
219 """
220
Note: See TracBrowser for help on using the repository browser.