Changeset 8:85698811c70e


Ignore:
Timestamp:
02/04/12 15:10:19 (12 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
hg-Phase:
(<MercurialRepository 1 'hg:/home/ivaradi/mlx/hg' '/'>, 'public')
Message:

The tracking of flight stages and some basic logging functionality works

Location:
src
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • src/acft.py

    r7 r8  
    33#---------------------------------------------------------------------------------------
    44
     5import const
     6import checks
     7
    58import time
    6 
    7 import const
    89
    910#---------------------------------------------------------------------------------------
     
    1112class Aircraft(object):
    1213    """Base class for aircraft."""
    13     def __init__(self, type):
     14    @staticmethod
     15    def create(flight):
     16        """Create an aircraft instance for the type in the given flight."""
     17        return _classes[flight.aircraftType](flight)
     18
     19    def __init__(self, flight):
    1420        """Construct the aircraft for the given type."""
    15         self._type = type
     21        self._flight = flight
    1622        self._aircraftState = None
     23
     24        self._checkers = []
     25
     26        self._checkers.append(checks.StageChecker())
     27
     28        self._checkers.append(checks.AltimeterLogger())
     29       
     30        self._checkers.append(checks.NAV1Logger())
     31        self._checkers.append(checks.NAV2Logger())
     32        self._checkers.append(checks.SquawkLogger())
     33
     34        self._checkers.append(checks.AnticollisionLightsLogger())
     35        self._checkers.append(checks.LandingLightsLogger())
     36        self._checkers.append(checks.StrobeLightsLogger())
     37        self._checkers.append(checks.NavLightsLogger())
     38
     39        self._checkers.append(checks.FlapsLogger())
     40
     41        self._checkers.append(checks.GearsLogger())
    1742
    1843    @property
    1944    def type(self):
    2045        """Get the type of the aircraft."""
    21         return self._type
    22 
    23     def modelChanged(self, aircraftName, modelName):
     46        return self._flight.aircraftType
     47
     48    @property
     49    def flight(self):
     50        """Get the flight the aircraft belongs to."""
     51        return self._flight
     52
     53    @property
     54    def logger(self):
     55        """Get the logger to use for the aircraft."""
     56        return self._flight.logger
     57
     58    def modelChanged(self, timestamp, aircraftName, modelName):
    2459        """Called when the simulator's aircraft changes."""
    25         print "Aircraft.modelChanged: aircraftName='%s', modelName='%s'" % \
    26             (aircraftName, modelName)
     60        self._flight.logger.message(timestamp,
     61                                    "Aircraft: name='%s', model='%s'" % \
     62                                    (aircraftName, modelName))
    2763
    2864    def handleState(self, aircraftState):
    2965        """Called when the state of the aircraft changes."""
    30         timeStr = time.ctime(aircraftState.timestamp)
    31 
    32         if self._aircraftState is None or \
    33            self._aircraftState.paused != aircraftState.paused:
    34             print "Aircraft.handleState: %s: paused=%d" % \
    35                 (timeStr, aircraftState.paused)
    36 
    37         if self._aircraftState is None or \
    38            self._aircraftState.trickMode != aircraftState.trickMode:
    39             print "Aircraft.handleState: %s: trickMode=%d" % \
    40                 (timeStr, aircraftState.trickMode)
    41 
    42         if self._aircraftState is None or \
    43            self._aircraftState.overspeed != aircraftState.overspeed:
    44             print "Aircraft.handleState: %s: overspeed=%d" % \
    45                 (timeStr, aircraftState.overspeed)
    46 
    47         if self._aircraftState is None or \
    48            self._aircraftState.stalled != aircraftState.stalled:
    49             print "Aircraft.handleState: %s: stalled=%d" % \
    50                 (timeStr, aircraftState.stalled)
    51 
    52         if self._aircraftState is None or \
    53            self._aircraftState.onTheGround != aircraftState.onTheGround:
    54             print "Aircraft.handleState: %s: onTheGround=%d" % \
    55                 (timeStr, aircraftState.onTheGround)
    56 
    57         if self._aircraftState is None or \
    58            self._aircraftState.grossWeight != aircraftState.grossWeight:
    59             print "Aircraft.handleState: %s: grossWeight=%f" % \
    60                 (timeStr, aircraftState.grossWeight)
    61 
    62         if self._aircraftState is None or \
    63            self._aircraftState.heading != aircraftState.heading:
    64             print "Aircraft.handleState: %s: heading=%f" % \
    65                 (timeStr, aircraftState.heading)
    66 
    67         if self._aircraftState is None or \
    68            self._aircraftState.pitch != aircraftState.pitch:
    69             print "Aircraft.handleState: %s: pitch=%f" % \
    70                 (timeStr, aircraftState.pitch)
    71 
    72         if self._aircraftState is None or \
    73            self._aircraftState.bank != aircraftState.bank:
    74             print "Aircraft.handleState: %s: bank=%f" % \
    75                 (timeStr, aircraftState.bank)
    76 
    77         if self._aircraftState is None or \
    78            self._aircraftState.ias != aircraftState.ias:
    79             print "Aircraft.handleState: %s: ias=%f" % \
    80                 (timeStr, aircraftState.ias)
    81 
    82         if self._aircraftState is None or \
    83            self._aircraftState.groundSpeed != aircraftState.groundSpeed:
    84             print "Aircraft.handleState: %s: groundSpeed=%f" % \
    85                 (timeStr, aircraftState.groundSpeed)
    86 
    87         if self._aircraftState is None or \
    88            self._aircraftState.vs != aircraftState.vs:
    89             print "Aircraft.handleState: %s: vs=%f" % \
    90                 (timeStr, aircraftState.vs)
    91 
    92         if self._aircraftState is None or \
    93            self._aircraftState.altitude != aircraftState.altitude:
    94             print "Aircraft.handleState: %s: altitude=%f" % \
    95                 (timeStr, aircraftState.altitude)
    96 
    97         if self._aircraftState is None or \
    98            self._aircraftState.gLoad != aircraftState.gLoad:
    99             print "Aircraft.handleState: %s: gLoad=%f" % \
    100                 (timeStr, aircraftState.gLoad)
    101 
    102         if self._aircraftState is None or \
    103            self._aircraftState.flapsSet != aircraftState.flapsSet:
    104             print "Aircraft.handleState: %s: flapsSet=%f" % \
    105                 (timeStr, aircraftState.flapsSet)
    106 
    107         if self._aircraftState is None or \
    108            self._aircraftState.flaps != aircraftState.flaps:
    109             print "Aircraft.handleState: %s: flaps=%f" % \
    110                 (timeStr, aircraftState.flaps)
    111 
    112         if self._aircraftState is None or \
    113            self._aircraftState.navLightsOn != aircraftState.navLightsOn:
    114             print "Aircraft.handleState: %s: navLightsOn=%d" % \
    115                 (timeStr, aircraftState.navLightsOn)
    116 
    117         if self._aircraftState is None or \
    118            self._aircraftState.antiCollisionLightsOn != aircraftState.antiCollisionLightsOn:
    119             print "Aircraft.handleState: %s: antiCollisionLightsOn=%d" % \
    120                 (timeStr, aircraftState.antiCollisionLightsOn)
    121 
    122         if self._aircraftState is None or \
    123            self._aircraftState.strobeLightsOn != aircraftState.strobeLightsOn:
    124             print "Aircraft.handleState: %s: strobeLightsOn=%d" % \
    125                 (timeStr, aircraftState.strobeLightsOn)
    126 
    127         if self._aircraftState is None or \
    128            self._aircraftState.landingLightsOn != aircraftState.landingLightsOn:
    129             print "Aircraft.handleState: %s: landingLightsOn=%d" % \
    130                 (timeStr, aircraftState.landingLightsOn)
    131 
    132         if self._aircraftState is None or \
    133            self._aircraftState.pitotHeatOn != aircraftState.pitotHeatOn:
    134             print "Aircraft.handleState: %s: pitotHeatOn=%d" % \
    135                 (timeStr, aircraftState.pitotHeatOn)
    136 
    137         if self._aircraftState is None or \
    138            self._aircraftState.gearsDown != aircraftState.gearsDown:
    139             print "Aircraft.handleState: %s: gearsDown=%f" % \
    140                 (timeStr, aircraftState.gearsDown)
    141 
    142         if self._aircraftState is None or \
    143            self._aircraftState.spoilersArmed != aircraftState.spoilersArmed:
    144             print "Aircraft.handleState: %s: spoilersArmed=%f" % \
    145                 (timeStr, aircraftState.spoilersArmed)
    146 
    147         if self._aircraftState is None or \
    148            self._aircraftState.spoilersExtension != aircraftState.spoilersExtension:
    149             print "Aircraft.handleState: %s: spoilersExtension=%f" % \
    150                 (timeStr, aircraftState.spoilersExtension)
    151 
    152         if self._aircraftState is None or \
    153            self._aircraftState.altimeter != aircraftState.altimeter:
    154             print "Aircraft.handleState: %s: altimeter=%f" % \
    155                 (timeStr, aircraftState.altimeter)
    156 
    157         if self._aircraftState is None or \
    158            self._aircraftState.nav1 != aircraftState.nav1:
    159             print "Aircraft.handleState: %s: nav1=%s" % \
    160                 (timeStr, aircraftState.nav1)
    161 
    162         if self._aircraftState is None or \
    163            self._aircraftState.nav2 != aircraftState.nav2:
    164             print "Aircraft.handleState: %s: nav2=%s" % \
    165                 (timeStr, aircraftState.nav2)
    166 
    167         if self._aircraftState is None or \
    168            self._aircraftState.fuel != aircraftState.fuel:
    169             print "Aircraft.handleState: %s: fuel=%s" % \
    170                 (timeStr, aircraftState.fuel)
    171 
    172         if self._aircraftState is None or \
    173            self._aircraftState.n1 != aircraftState.n1:
    174             print "Aircraft.handleState: %s: n1=%s" % \
    175                 (timeStr, aircraftState.n1)
    176 
    177         if self._aircraftState is None or \
    178            self._aircraftState.reverser != aircraftState.reverser:
    179             print "Aircraft.handleState: %s: reverser=%s" % \
    180                 (timeStr, aircraftState.reverser)
     66        for checker in self._checkers:
     67            checker.check(self._flight, self, self._flight.logger,
     68                          self._aircraftState, aircraftState)
    18169
    18270        self._aircraftState = aircraftState
    183            
     71   
     72    def setStage(self, aircraftState, newStage):
     73        """Set the given stage as the new one and do whatever should be
     74        done."""
     75        self._flight.setStage(aircraftState.timestamp, newStage)
     76
     77    def flare(self):
     78        """Called when it is detected that we are during flare.
     79
     80        On the first call, it should start monitoring some parameters more
     81        closely to determine flare time."""
     82        pass
     83
     84    def cancelFlare(self):
     85        """Cancel flare, if it has started."""
     86        pass
     87
     88    def checkFlightEnd(self, aircraftState):
     89        """Check if the end of the flight has arrived.
     90
     91        This default implementation checks the N1 values, but for
     92        piston-powered aircraft you need to check the RPMs."""
     93        for n1 in aircraftState.n1:
     94            if n1>=0.5: return False
     95        return True
     96
    18497#---------------------------------------------------------------------------------------
    18598
     
    198111class B736(Boeing737):
    199112    """Boeing 737-600 aircraft."""
    200     def __init__(self):
    201         super(B736, self).__init__(const.AIRCRAFT_B736)
     113    def __init__(self, flight):
     114        super(B736, self).__init__(flight)
    202115
    203116#---------------------------------------------------------------------------------------
     
    205118class B737(Boeing737):
    206119    """Boeing 737-700 aircraft."""
    207     def __init__(self):
    208         super(B737, self).__init__(const.AIRCRAFT_B737)
     120    def __init__(self, flight):
     121        super(B737, self).__init__(flight)
    209122
    210123#---------------------------------------------------------------------------------------
     
    212125class B738(Boeing737):
    213126    """Boeing 737-800 aircraft."""
    214     def __init__(self):
    215         super(B738, self).__init__(const.AIRCRAFT_B738)
     127    def __init__(self, flight):
     128        super(B738, self).__init__(flight)
    216129
    217130#---------------------------------------------------------------------------------------
     
    219132class B733(Boeing737):
    220133    """Boeing 737-300 aircraft."""
    221     def __init__(self):
    222         super(B733, self).__init__(const.AIRCRAFT_B733)
     134    def __init__(self, flight):
     135        super(B733, self).__init__(flight)
    223136
    224137#---------------------------------------------------------------------------------------
     
    226139class B734(Boeing737):
    227140    """Boeing 737-400 aircraft."""
    228     def __init__(self):
    229         super(B734, self).__init__(const.AIRCRAFT_B734)
     141    def __init__(self, flight):
     142        super(B734, self).__init__(flight)
    230143
    231144#---------------------------------------------------------------------------------------
     
    233146class B735(Boeing737):
    234147    """Boeing 737-500 aircraft."""
    235     def __init__(self):
    236         super(B735, self).__init__(const.AIRCRAFT_B735)
     148    def __init__(self, flight):
     149        super(B735, self).__init__(flight)
    237150
    238151#---------------------------------------------------------------------------------------
     
    246159    - n1: left, right
    247160    - reverser: left, right."""
    248     def __init__(self):
    249         super(DH8D, self).__init__(const.AIRCRAFT_DH8D)
     161    def __init__(self, flight):
     162        super(DH8D, self).__init__(flight)
    250163
    251164#---------------------------------------------------------------------------------------
     
    264177class B762(Boeing767):
    265178    """Boeing 767-200 aircraft."""
    266     def __init__(self):
    267         super(B762, self).__init__(const.AIRCRAFT_B762)
     179    def __init__(self, flight):
     180        super(B762, self).__init__(flight)
    268181
    269182#---------------------------------------------------------------------------------------
     
    271184class B763(Boeing767):
    272185    """Boeing 767-300 aircraft."""
    273     def __init__(self):
    274         super(B763, self).__init__(const.AIRCRAFT_B763)
     186    def __init__(self, flight):
     187        super(B763, self).__init__(cflight)
    275188
    276189#---------------------------------------------------------------------------------------
     
    284197    - n1: left, right
    285198    - reverser: left, right."""
    286     def __init__(self):
    287         super(CRJ2, self).__init__(const.AIRCRAFT_CRJ2)
     199    def __init__(self, flight):
     200        super(CRJ2, self).__init__(flight)
    288201
    289202#---------------------------------------------------------------------------------------
     
    297210    - n1: left, right
    298211    - reverser: left, right."""
    299     def __init__(self):
    300         super(F70, self).__init__(const.AIRCRAFT_F70)
     212    def __init__(self, flight):
     213        super(F70, self).__init__(flight)
    301214
    302215#---------------------------------------------------------------------------------------
     
    310223    - rpm: left, right
    311224    - reverser: left, right."""
    312     def __init__(self):
    313         super(DC3, self).__init__(const.AIRCRAFT_DC3)
     225    def __init__(self, flight):
     226        super(DC3, self).__init__(flight)
     227
     228    def _checkFlightEnd(self, aircraftState):
     229        """Check if the end of the flight has arrived.
     230
     231        This implementation checks the RPM values to be 0."""
     232        for rpm in aircraftState.rpm:
     233            if rpm>0: return
     234        self._setStage(aircraftState, const.STAGE_END)
    314235
    315236#---------------------------------------------------------------------------------------
     
    324245    - n1: left, right
    325246    - reverser: left, right."""
    326     def __init__(self):
    327         super(T134, self).__init__(const.AIRCRAFT_T134)
     247    def __init__(self, flight):
     248        super(T134, self).__init__(flight)
    328249
    329250#---------------------------------------------------------------------------------------
     
    337258    - n1: left, centre, right
    338259    - reverser: left, right"""
    339     def __init__(self):
    340         super(T154, self).__init__(const.AIRCRAFT_T154)
     260    def __init__(self, flight):
     261        super(T154, self).__init__(flight)
    341262
    342263#---------------------------------------------------------------------------------------
     
    350271    - n1: left, right
    351272    - reverser: left, right"""
    352     def __init__(self):
    353         super(YK40, self).__init__(const.AIRCRAFT_YK40)
    354 
    355 #---------------------------------------------------------------------------------------
    356 
     273    def __init__(self, flight):
     274        super(YK40, self).__init__(flight)
     275
     276#---------------------------------------------------------------------------------------
     277
     278_classes = { const.AIRCRAFT_B736 : B736,
     279             const.AIRCRAFT_B737 : B737,
     280             const.AIRCRAFT_B738 : B738,
     281             const.AIRCRAFT_B733 : B733,
     282             const.AIRCRAFT_B734 : B734,
     283             const.AIRCRAFT_B735 : B735,
     284             const.AIRCRAFT_DH8D : DH8D,
     285             const.AIRCRAFT_B762 : B762,
     286             const.AIRCRAFT_B763 : B763,
     287             const.AIRCRAFT_CRJ2 : CRJ2,
     288             const.AIRCRAFT_F70 : F70,
     289             const.AIRCRAFT_DC3 : DC3,
     290             const.AIRCRAFT_T134 : T134,
     291             const.AIRCRAFT_T154 : T154,
     292             const.AIRCRAFT_YK40 : YK40 }
     293
     294#---------------------------------------------------------------------------------------
  • src/const.py

    r7 r8  
    7070AIRCRAFT_YK40 = 15
    7171
     72#-------------------------------------------------------------------------------
     73
     74# Flight stage: boarding
     75STAGE_BOARDING = 1
     76
     77# Flight stage: pushback, startup and taxi
     78STAGE_PUSHANDTAXI = 2
     79
     80# Flight stage: takeoff
     81STAGE_TAKEOFF = 3
     82
     83# Flight stage: RTO
     84STAGE_RTO = 4
     85
     86# Flight stage: climb
     87STAGE_CLIMB = 5
     88
     89# Flight stage: cruise
     90STAGE_CRUISE = 6
     91
     92# Flight stage: descent
     93STAGE_DESCENT = 7
     94
     95# Flight stage: landing
     96STAGE_LANDING = 8
     97
     98# Flight stage: taxi after landing
     99STAGE_TAXIAFTERLAND = 9
     100
     101# Flight stage: parking
     102STAGE_PARKING = 10
     103
     104# Flight stage: go-around
     105STAGE_GOAROUND = 11
     106
     107# Flight stage: end
     108STAGE_END = 12
  • src/fs.py

    r6 r8  
    6262    - groundSpeed: the ground speed (float)
    6363    - vs: the vertical speed in feet/minutes (float)
     64    - radioAltitude: the radio altitude of the aircraft in feet (float)
    6465    - altitude: the altitude of the aircraft in feet (float)
    6566    - gLoad: G-load (float)
     
    8283    - langingLightsOn: a boolean indicating if the landing lights are on
    8384    - pitotHeatOn: a boolean indicating if the pitot heat is on
     85    - parking: a boolean indicating if the parking brake is set
    8486    - gearsDown: a boolean indicating if the gears are down
    8587    - spoilersArmed: a boolean indicating if the spoilers have been armed for
     
    9092    - nav1: the frequency of the NAV1 radio in MHz (string)
    9193    - nav2: the frequency of the NAV1 radio in MHz (string)
     94    - squawk: the transponder code
    9295
    9396    FIXME: needed when taxiing only:
  • src/fsuipc.py

    r7 r8  
    341341    via FSUIPC."""
    342342    # The basic data that should be queried all the time once we are connected
    343     normalData = [ (0x3d00, -256) ]
    344 
     343    normalData = [ (0x0240, "H"),
     344                   (0x023e, "H"),
     345                   (0x023b, "b"),
     346                   (0x023c, "b"),
     347                   (0x023a, "b"),
     348                   (0x3d00, -256),
     349                   (0x3c00, -256) ]
     350   
    345351    def __init__(self, connectionListener, aircraft):
    346352        """Construct the simulator.
     
    407413        aircraft-specific values.
    408414        """
    409         self._setAircraftName(data[0])
     415        timestamp = calendar.timegm(time.struct_time([data[0],
     416                                                      1, 1, 0, 0, 0, -1, 1, 0]))
     417        timestamp += data[1] * 24 * 3600
     418        timestamp += data[2] * 3600
     419        timestamp += data[3] * 60
     420        timestamp += data[4]       
     421
     422        createdNewModel = self._setAircraftName(timestamp, data[5], data[6])
     423       
    410424        if self._monitoringRequested and not self._monitoring:
    411425            self._monitoring = True
     
    416430            self._stopNormal()
    417431            self._startDefaultNormal()
    418         elif self._monitoring and self._aircraftModel is not None:
    419             aircraftState = self._aircraftModel.getAircraftState(self._aircraft, data)
     432        elif self._monitoring and self._aircraftModel is not None and \
     433             not createdNewModel:
     434            aircraftState = self._aircraftModel.getAircraftState(self._aircraft,
     435                                                                 timestamp, data)
    420436            self._aircraft.handleState(aircraftState)
    421437
    422     def _setAircraftName(self, name):
     438    def _setAircraftName(self, timestamp, name, airPath):
    423439        """Set the name of the aicraft and if it is different from the
    424440        previous, create a new model for it.
    425441       
    426         If so, also notifty the aircraft about the change."""
    427         if name==self._aircraftName:
    428             return
    429 
    430         self._aircraftName = name
    431         if self._aircraftModel is None or \
    432            not self._aircraftModel.doesHandle(name):           
    433             self._setAircraftModel(AircraftModel.create(self._aircraft, name))
    434        
    435         self._aircraft.modelChanged(self._aircraftName,
    436                                     self._aircraftModel.name)
     442        If so, also notifty the aircraft about the change.
     443
     444        Return if a new model was created."""
     445        aircraftName = (name, airPath)
     446        if aircraftName==self._aircraftName:
     447            return False
     448
     449        self._aircraftName = aircraftName
     450        needNew = self._aircraftModel is None
     451        needNew = needNew or\
     452            not self._aircraftModel.doesHandle(self._aircraft, aircraftName)
     453        if not needNew:
     454            specialModel = AircraftModel.findSpecial(self._aircraft, aircraftName)
     455            needNew = specialModel is not None and \
     456                specialModel is not self._aircraftModel.__class__
     457
     458        if needNew:
     459            self._setAircraftModel(AircraftModel.create(self._aircraft, aircraftName))
     460       
     461        self._aircraft.modelChanged(timestamp, name, self._aircraftModel.name)       
     462
     463        return needNew
    437464
    438465    def _setAircraftModel(self, model):
     
    444471       
    445472        if self._monitoring:
    446             self._handler.clearPeriodic(self._normalRequestID)           
     473            self._stopNormal()
    447474            self._startMonitoring()
    448475           
     
    465492    Aircraft models handle the data arriving from FSUIPC and turn it into an
    466493    object describing the aircraft's state."""
    467     monitoringData = [("year", 0x0240, "H"),
    468                       ("dayOfYear", 0x023e, "H"),
    469                       ("zuluHour", 0x023b, "b"),
    470                       ("zuluMinute", 0x023c, "b"),
    471                       ("seconds", 0x023a, "b"),
    472                       ("paused", 0x0264, "H"),
     494    monitoringData = [("paused", 0x0264, "H"),
    473495                      ("frozen", 0x3364, "H"),
    474496                      ("replay", 0x0628, "d"),
     
    484506                      ("groundSpeed", 0x02b4, "d"),
    485507                      ("vs", 0x02c8, "d"),
     508                      ("radioAltitude", 0x31e4, "d"),
    486509                      ("altitude", 0x0570, "l"),
    487510                      ("gLoad", 0x11ba, "H"),
     
    491514                      ("lights", 0x0d0c, "H"),
    492515                      ("pitot", 0x029c, "b"),
     516                      ("parking", 0x0bc8, "H"),
    493517                      ("noseGear", 0x0bec, "d"),
    494518                      ("spoilersArmed", 0x0bcc, "d"),
     
    496520                      ("altimeter", 0x0330, "H"),
    497521                      ("nav1", 0x0350, "H"),
    498                       ("nav2", 0x0352, "H")]
    499 
    500     genericModels = { const.AIRCRAFT.B736 : B737Model,
    501                       const.AIRCRAFT_B737 : B737Model,
    502                       const.AIRCRAFT_B738 : B737Model,
    503                       const.AIRCRAFT_B733 : B737Model,
    504                       const.AIRCRAFT_B734 : B737Model,
    505                       const.AIRCRAFT_B735 : B737Model,
    506                       const.AIRCRAFT_DH8D : DH8DModel,
    507                       const.AIRCRAFT_B762 : B767Model,
    508                       const.AIRCRAFT_B763 : B767Model,
    509                       const.AIRCRAFT_CRJ2 : B767Model,
    510                       const.AIRCRAFT_F79  : F70Model,
    511                       const.AIRCRAFT_DC3  : DC3Model,
    512                       const.AIRCRAFT_T134 : T134Model,
    513                       const.AIRCRAFT_T154 : T154Model,
    514                       const.AIRCRAFT_YK40 : YK40Model }
     522                      ("nav2", 0x0352, "H"),
     523                      ("squawk", 0x0354, "H")]
    515524
    516525    specialModels = []
     
    522531
    523532    @staticmethod
     533    def findSpecial(aircraft, aircraftName):
     534        for specialModel in AircraftModel.specialModels:
     535            if specialModel.doesHandle(aircraft, aircraftName):
     536                return specialModel
     537        return None
     538
     539    @staticmethod
    524540    def create(aircraft, aircraftName):
    525541        """Create the model for the given aircraft name, and notify the
    526542        aircraft about it."""
    527         for specialModel in AircraftModel.specialModels:
    528             if specialModel.doesHandle(aircraft, aircraftName):
    529                 return specialModel(aircraft, aircraftName)
    530        
    531         if aircraft.type in AircraftModel.genericModels:
    532             return AircraftModel.genericModels[aircraft.type]()
     543        specialModel = AircraftModel.findSpecial(aircraft, aircraftName)
     544        if specialModel is not None:
     545            return specialModel()
     546        if aircraft.type in _genericModels:
     547            return _genericModels[aircraft.type]()
    533548        else:
    534549            return GenericModel()
     550
     551    @staticmethod
     552    def convertBCD(data, length):
     553        """Convert a data item encoded as BCD into a string of the given number
     554        of digits."""
     555        bcd = ""
     556        for i in range(0, length):
     557            digit = chr(ord('0') + (data&0x0f))
     558            data >>= 4
     559            bcd = digit + bcd
     560        return bcd
    535561
    536562    @staticmethod
    537563    def convertFrequency(data):
    538564        """Convert the given frequency data to a string."""
    539         frequency = ""
    540         for i in range(0, 4):
    541             digit = chr(ord('0') + (data&0x0f))
    542             data >>= 4
    543             frequency = digit + frequency
    544             if i==1:
    545                 frequency = "." + frequency
    546         return "1" + frequency           
     565        bcd = AircraftModel.convertBCD(data, 4)
     566        return "1" + bcd[0:2] + "." + bcd[2:4]
    547567
    548568    def __init__(self, flapsNotches):
     
    557577        return "FSUIPC/Generic"
    558578   
    559     def doesHandle(self, aircraftName):
     579    def doesHandle(self, aircraft, aircraftName):
    560580        """Determine if the model handles the given aircraft name.
    561581       
     
    568588        dest.append((offset, type))
    569589        if attrName is not None:
    570             setattr(self, attrName, len(dest))
     590            setattr(self, attrName, len(dest)-1)
    571591
    572592    def _addDataWithIndexMembers(self, dest, prefix, data):
     
    586606    def addMonitoringData(self, data):
    587607        """Add the model-specific monitoring data to the given array."""
    588         self.addDataWithIndexMembers(data, "_monidx_",
    589                                      AircraftModel.monitoringData)
     608        self._addDataWithIndexMembers(data, "_monidx_",
     609                                      AircraftModel.monitoringData)
    590610   
    591     def getAircraftState(self, aircraft, data):
     611    def getAircraftState(self, aircraft, timestamp, data):
    592612        """Get an aircraft state object for the given monitoring data."""
    593613        state = fs.AircraftState()
    594614       
    595         timestamp = calendar.timegm(time.struct_time([data[self._monidx_year],
    596                                                       1, 1, 0, 0, 0, -1, 1, 0]))
    597         timestamp += data[self._monidx_dayOfYear] * 24 * 3600
    598         timestamp += data[self._monidx_zuluHour] * 3600
    599         timestamp += data[self._monidx_zuluMinute] * 60
    600         timestamp += data[self._monidx_seconds]       
    601615        state.timestamp = timestamp
    602616       
     
    622636        state.vs = data[self._monidx_vs]*60.0/const.FEETTOMETRES/256.0
    623637
     638        state.radioAltitude = data[self._monidx_radioAltitude]/const.FEETTOMETRES/65536.0
    624639        state.altitude = data[self._monidx_altitude]/const.FEETTOMETRES/65536.0/65536.0
    625640
     
    655670        state.pitotHeatOn = data[self._monidx_pitot]!=0
    656671
     672        state.parking = data[self._monidx_parking]!=0
     673
    657674        state.gearsDown = data[self._monidx_noseGear]==16383
    658675
     
    669686        state.nav1 = AircraftModel.convertFrequency(data[self._monidx_nav1])
    670687        state.nav2 = AircraftModel.convertFrequency(data[self._monidx_nav2])
     688        state.squawk = AircraftModel.convertBCD(data[self._monidx_squawk], 4)
    671689       
    672690        return state
     
    699717        self._isN1 = isN1
    700718
     719    def doesHandle(self, aircraft, aircraftName):
     720        """Determine if the model handles the given aircraft name.
     721       
     722        This implementation returns True."""
     723        return True
     724
    701725    def addMonitoringData(self, data):
    702726        """Add the model-specific monitoring data to the given array."""
     
    716740                self._addOffsetWithIndexMember(data, 0x088c + i * 0x98, "d")  # throttle lever
    717741       
    718     def getAircraftState(self, aircraft, data):
     742    def getAircraftState(self, aircraft, timestamp, data):
    719743        """Get the aircraft state.
    720744
     
    722746        the engine parameters."""
    723747        state = super(GenericAircraftModel, self).getAircraftState(aircraft,
     748                                                                   timestamp,
    724749                                                                   data)
    725750
     
    746771    def __init__(self):
    747772        """Construct the model."""
    748         super(GenericAircraftModel, self).
     773        super(GenericModel, self). \
    749774            __init__(flapsNotches = [0, 10, 20, 30],
    750775                     fuelInfo = [0x0b74, 0x0b7c, 0xb94],
     
    762787    def __init__(self):
    763788        """Construct the model."""
    764         super(GenericAircraftModel, self).
     789        super(B737Model, self). \
    765790            __init__(flapsNotches = [0, 1, 2, 5, 10, 15, 25, 30, 40],
    766791                     fuelInfo = [0x0b74, 0x0b7c, 0xb94],
     
    771796        """Get the name for this aircraft model."""
    772797        return "FSUIPC/Generic Boeing 737"
     798
     799#------------------------------------------------------------------------------
     800
     801class PMDGBoeing737NGModel(B737Model):
     802    """A model handler for the PMDG Boeing 737NG model."""
     803    @staticmethod
     804    def doesHandle(aircraft, (name, airPath)):
     805        """Determine if this model handler handles the aircraft with the given
     806        name."""
     807        return aircraft.type in [const.AIRCRAFT_B736,
     808                                 const.AIRCRAFT_B737,
     809                                 const.AIRCRAFT_B738] and \
     810            (name.find("PMDG")!=-1 or airPath.find("PMDG")!=-1) and \
     811            (name.find("737")!=-1 or airPath.find("737")!=-1) and \
     812            (name.find("600")!=-1 or airPath.find("600")!=-1 or \
     813             name.find("700")!=-1 or airPath.find("700")!=-1 or \
     814             name.find("800")!=-1 or airPath.find("800")!=-1 or \
     815             name.find("900")!=-1 or airPath.find("900")!=-1)
     816
     817    @property
     818    def name(self):
     819        """Get the name for this aircraft model."""
     820        return "FSUIPC/PMDG Boeing 737NG"
     821
     822    def addMonitoringData(self, data):
     823        """Add the model-specific monitoring data to the given array."""
     824        super(PMDGBoeing737NGModel, self).addMonitoringData(data)
     825               
     826        self._addOffsetWithIndexMember(data, 0x6202, "b", "_pmdgidx_switches")
     827
     828    def getAircraftState(self, aircraft, timestamp, data):
     829        """Get the aircraft state.
     830
     831        Get it from the parent, and then check some PMDG-specific stuff."""
     832        state = super(PMDGBoeing737NGModel, self).getAircraftState(aircraft,
     833                                                                   timestamp,
     834                                                                   data)
     835        if data[self._pmdgidx_switches]&0x01==0x01:
     836            state.altimeter = 1013.25
     837
     838        return state
    773839
    774840#------------------------------------------------------------------------------
     
    778844    def __init__(self):
    779845        """Construct the model."""
    780         super(GenericAircraftModel, self).
     846        super(B767Model, self). \
    781847            __init__(flapsNotches = [0, 1, 5, 15, 20, 25, 30],
    782848                     fuelInfo = [0x0b74, 0x0b7c, 0xb94],
     
    794860    def __init__(self):
    795861        """Construct the model."""
    796         super(GenericAircraftModel, self).
     862        super(DH8DModel, self). \
    797863            __init__(flapsNotches = [0, 5, 10, 15, 35],
    798864                     fuelInfo = [0x0b74, 0x0b7c, 0xb94],
     
    810876    def __init__(self):
    811877        """Construct the model."""
    812         super(GenericAircraftModel, self).
     878        super(CRJ2Model, self). \
    813879            __init__(flapsNotches = [0, 8, 20, 30, 45],
    814880                     fuelInfo = [0x0b74, 0x0b7c, 0xb94],
     
    826892    def __init__(self):
    827893        """Construct the model."""
    828         super(GenericAircraftModel, self).
     894        super(F70Model, self). \
    829895            __init__(flapsNotches = [0, 8, 15, 25, 42],
    830896                     fuelInfo = [0x0b74, 0x0b7c, 0xb94],
     
    842908    def __init__(self):
    843909        """Construct the model."""
    844         super(GenericAircraftModel, self).
     910        super(DC3Model, self). \
    845911            __init__(flapsNotches = [0, 15, 30, 45],
    846912                     fuelInfo = [0x0b7c, 0x0b84, 0x0b94, 0x0b9c],
     
    858924    def __init__(self):
    859925        """Construct the model."""
    860         super(GenericAircraftModel, self).
     926        super(T134Model, self). \
    861927            __init__(flapsNotches = [0, 10, 20, 30],
    862928                     fuelInfo = [0x0b74,
     
    877943    def __init__(self):
    878944        """Construct the model."""
    879         super(GenericAircraftModel, self).
     945        super(T154Model, self). \
    880946            __init__(flapsNotches = [0, 15, 28, 45],
    881947                     fuelInfo = [0x0b74, 0x0b7c, 0x0b94,
    882                                  0x1244, 0x0b84, 0x0b9c]
     948                                 0x1244, 0x0b84, 0x0b9c],
    883949                     numEngines = 3)
    884950
     
    888954        return "FSUIPC/Generic Tupolev Tu-154"
    889955
    890     def getAircraftState(self, aircraft, data):
     956    def getAircraftState(self, aircraft, timestamp, data):
    891957        """Get an aircraft state object for the given monitoring data.
    892958
    893959        This removes the reverser value for the middle engine."""
    894         state = super(T154Model, self).getAircraftState(aircraft, data)
     960        state = super(T154Model, self).getAircraftState(aircraft, timestamp, data)
    895961        del state.reverser[1]
    896962        return state
     
    902968    def __init__(self):
    903969        """Construct the model."""
    904         super(GenericAircraftModel, self).
     970        super(YK40Model, self). \
    905971            __init__(flapsNotches = [0, 20, 35],
    906                      fuelInfo = [0x0b7c, 0x0b94]
     972                     fuelInfo = [0x0b7c, 0x0b94],
    907973                     numEngines = 2)
    908974
     
    914980#------------------------------------------------------------------------------
    915981
     982_genericModels = { const.AIRCRAFT_B736 : B737Model,
     983                   const.AIRCRAFT_B737 : B737Model,
     984                   const.AIRCRAFT_B738 : B737Model,
     985                   const.AIRCRAFT_B733 : B737Model,
     986                   const.AIRCRAFT_B734 : B737Model,
     987                   const.AIRCRAFT_B735 : B737Model,
     988                   const.AIRCRAFT_DH8D : DH8DModel,
     989                   const.AIRCRAFT_B762 : B767Model,
     990                   const.AIRCRAFT_B763 : B767Model,
     991                   const.AIRCRAFT_CRJ2 : B767Model,
     992                   const.AIRCRAFT_F70  : F70Model,
     993                   const.AIRCRAFT_DC3  : DC3Model,
     994                   const.AIRCRAFT_T134 : T134Model,
     995                   const.AIRCRAFT_T154 : T154Model,
     996                   const.AIRCRAFT_YK40 : YK40Model }
     997
     998#------------------------------------------------------------------------------
     999
     1000AircraftModel.registerSpecial(PMDGBoeing737NGModel)
     1001
     1002#------------------------------------------------------------------------------
     1003
  • src/test.py

    r6 r8  
    22
    33import fs
     4import flight
     5import logger
    46import acft
    57import const
     8
    69import time
     10import sys
    711
    812def callback(data, extra):
     
    1014
    1115def main():
    12     simulator = fs.createSimulator(const.SIM_MSFS9, fs.ConnectionListener(),
    13                                    acft.Aircraft(const.AIRCRAFT_B737))
    14     simulator.connect()
     16    with open(sys.argv[1], "wt") as output:
     17        fl = flight.Flight(logger.Logger(output = output))
     18        fl.cruiseAltitude = 18000
     19        fl.aircraftType = const.AIRCRAFT_B736
     20        fl.aircraft = acft.Aircraft.create(fl)
     21        simulator = fs.createSimulator(const.SIM_MSFS9, fs.ConnectionListener(),
     22                                       fl.aircraft)
     23        fl.simulator = simulator
    1524
    16     time.sleep(10)
    17     simulator.startMonitoring()
     25        simulator.connect()
     26        simulator.startMonitoring()
     27       
     28        fl.wait()
    1829
    19     while True:
    20         time.sleep(1000)
    21     simulator.stopMonitoring()
    22     simulator.disconnect()
    23 
    24     time.sleep(5)
     30        simulator.stopMonitoring()
     31        simulator.disconnect()
    2532
    2633if __name__ == "__main__":
Note: See TracChangeset for help on using the changeset viewer.