Ignore:
Timestamp:
02/04/12 15:10:19 (12 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

The tracking of flight stages and some basic logging functionality works

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.