Changeset 97:f885322fb296


Ignore:
Timestamp:
04/21/12 14:49:45 (12 years ago)
Author:
István Váradi <ivaradi@…>
Branch:
default
Phase:
public
Message:

The PIREP can be created and sent.

Location:
src/mlx
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • src/mlx/const.py

    r82 r97  
    132132#-------------------------------------------------------------------------------
    133133
     134# Flight type: scheduled
     135FLIGHTTYPE_SCHEDULED = 0
     136
     137# Flight type: old-timer
     138FLIGHTTYPE_OLDTIMER = 1
     139
     140# Flight type: VIP
     141FLIGHTTYPE_VIP = 2
     142
     143# Flight type: charter
     144FLIGHTTYPE_CHARTER = 3
     145
     146#-------------------------------------------------------------------------------
     147
    134148# The available gates at LHBP
    135149lhbpGateNumbers = []
  • src/mlx/fsuipc.py

    r89 r97  
    642642 
    643643       
    644         self._aircraft.modelChanged(timestamp, self._latin1decoder(name),
     644        self._aircraft.modelChanged(timestamp, self._latin1decoder(name)[0],
    645645                                    self._aircraftModel.name)       
    646646
  • src/mlx/gui/common.py

    r93 r97  
    2121    MESSAGETYPE_ERROR = gtk.MESSAGE_ERROR
    2222    MESSAGETYPE_QUESTION = gtk.MESSAGE_QUESTION
     23    MESSAGETYPE_INFO = gtk.MESSAGE_INFO
    2324    BUTTONSTYPE_OK = gtk.BUTTONS_OK
    2425    BUTTONSTYPE_YES_NO = gtk.BUTTONS_YES_NO
     
    2627    ACCEL_VISIBLE = gtk.ACCEL_VISIBLE
    2728    CONTROL_MASK = gdk.CONTROL_MASK
     29
     30    def text2unicode(text):
     31        """Convert the given text, returned by a Gtk widget, to Unicode."""
     32        return unicode(text)
    2833else:
    2934    print "Using PyGObject"
     
    3843    MESSAGETYPE_ERROR = gtk.MessageType.ERROR
    3944    MESSAGETYPE_QUESTION = gtk.MessageType.QUESTION
     45    MESSAGETYPE_INFO = gtk.MessageType.INFO
    4046    BUTTONSTYPE_OK = gtk.ButtonsType.OK
    4147    BUTTONSTYPE_YES_NO = gtk.ButtonsType.YES_NO
     
    4349    ACCEL_VISIBLE = gtk.AccelFlags.VISIBLE
    4450    CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
     51
     52    import codecs
     53    _utf8Decoder = codecs.getdecoder("utf-8")
     54   
     55    def text2unicode(str):
     56        """Convert the given text, returned by a Gtk widget, to Unicode."""
     57        return _utf8Decoder(str)[0]
    4558
    4659import cairo
  • src/mlx/gui/flight.py

    r96 r97  
    77from mlx.checks import PayloadChecker
    88import mlx.util as util
     9from mlx.pirep import PIREP
    910
    1011import datetime
     
    777778        self._button.connect("clicked", self._forwardClicked)
    778779
     780    @property
     781    def cargoWeight(self):
     782        """Get the cargo weight entered."""
     783        return self._cargoWeight.get_int()
     784
    779785    def activate(self):
    780786        """Setup the information."""
     
    9961002        self._cruiseLevel.set_numeric(True)
    9971003        self._cruiseLevel.connect("value-changed", self._cruiseLevelChanged)
    998         label.set_mnemonic_widget(self._cruiseLevel)       
     1004        label.set_mnemonic_widget(self._cruiseLevel)
     1005        self._filedCruiseLevel = 240
    9991006
    10001007        levelBox.pack_start(self._cruiseLevel, False, False, 8)
     
    10441051
    10451052    @property
     1053    def filedCruiseLevel(self):
     1054        """Get the filed cruise level."""
     1055        return self._filedCruiseLevel
     1056
     1057    @property
    10461058    def cruiseLevel(self):
    10471059        """Get the cruise level."""
    10481060        return self._cruiseLevel.get_value_as_int()
    10491061
     1062    @property
     1063    def route(self):
     1064        """Get the route."""
     1065        return self._getRoute()
     1066
    10501067    def activate(self):
    10511068        """Setup the route from the booked flight."""
    10521069        self._cruiseLevel.set_value(240)
     1070        self._filedCruiseLevel = 240
    10531071        self._route.get_buffer().set_text(self._wizard._bookedFlight.route)
    10541072        self._updateForwardButton()
     
    10831101        else:
    10841102            bookedFlight = self._wizard._bookedFlight
     1103            self._filedCruiseLevel = self.cruiseLevel
    10851104            self._wizard.gui.beginBusy("Downloading NOTAMs...")
    10861105            self._wizard.gui.webHandler.getNOTAMs(self._notamsCallback,
     
    12041223        self._button.connect("clicked", self._forwardClicked)
    12051224
     1225    @property
     1226    def metar(self):
     1227        """Get the METAR on the page."""
     1228        buffer = self._metar.get_buffer()
     1229        return buffer.get_text(buffer.get_start_iter(),
     1230                               buffer.get_end_iter(), True)       
     1231
    12061232    def activate(self):
    12071233        """Activate the page."""
     
    13571383
    13581384    @property
     1385    def runway(self):
     1386        """Get the runway."""
     1387        return self._runway.get_text()
     1388
     1389    @property
     1390    def sid(self):
     1391        """Get the SID."""
     1392        return self._sid.get_text()
     1393
     1394    @property
    13591395    def v1(self):
    13601396        """Get the v1 speed."""
     
    15141550
    15151551    @property
     1552    def star(self):
     1553        """Get the STAR or None if none entered."""
     1554        return self._star.get_text() if self._starButton.get_active() else None
     1555
     1556    @property
     1557    def transition(self):
     1558        """Get the transition or None if none entered."""
     1559        return self._transition.get_text() \
     1560               if self._transitionButton.get_active() else None
     1561
     1562    @property
     1563    def approachType(self):
     1564        """Get the approach type."""
     1565        return self._approachType.get_text()
     1566
     1567    @property
     1568    def runway(self):
     1569        """Get the runway."""
     1570        return self._runway.get_text()
     1571
     1572    @property
    15161573    def vref(self):
    15171574        """Return the landing reference speed."""
     
    16081665class FinishPage(Page):
    16091666    """Flight finish page."""
     1667    _flightTypes = [ ("scheduled", const.FLIGHTTYPE_SCHEDULED),
     1668                     ("old-timer", const.FLIGHTTYPE_OLDTIMER),
     1669                     ("VIP", const.FLIGHTTYPE_VIP),
     1670                     ("charter", const.FLIGHTTYPE_CHARTER) ]
     1671   
    16101672    def __init__(self, wizard):
    16111673        """Construct the finish page."""
     
    16981760
    16991761        flightTypeModel = gtk.ListStore(str, int)
    1700         index = 1
    1701         for type in ["scheduled", "old-timer", "VIP", "charter"]:
    1702             flightTypeModel.append([type, index])
    1703             index += 1
     1762        for (name, type) in FinishPage._flightTypes:
     1763            flightTypeModel.append([name, type])
    17041764
    17051765        self._flightType = gtk.ComboBox(model = flightTypeModel)
     
    17341794        self._sendButton.set_use_underline(True)
    17351795        self._sendButton.set_sensitive(False)
    1736         #self._sendButton.connect("clicked", self._sendClicked)
     1796        self._sendButton.connect("clicked", self._sendClicked)
     1797       
     1798    @property
     1799    def flightType(self):
     1800        """Get the flight type."""
     1801        index = self._flightType.get_active()
     1802        return None if index<0 else self._flightType.get_model()[index][1]
     1803
     1804    @property
     1805    def online(self):
     1806        """Get whether the flight was an online flight or not."""
     1807        return self._onlineFlight.get_active()
    17371808
    17381809    def activate(self):
     
    17701841        index = self._flightType.get_active()
    17711842        flightTypeIsValid = index>=0
    1772         self._saveButton.set_sensitive(flightTypeIsValid)
     1843        #self._saveButton.set_sensitive(flightTypeIsValid)
    17731844        self._sendButton.set_sensitive(flightTypeIsValid)
     1845
     1846    def _sendClicked(self, button):
     1847        """Called when the Send button is clicked."""
     1848        pirep = PIREP(self._wizard.gui)
     1849        gui = self._wizard.gui
     1850        gui.beginBusy("Sending PIREP...")
     1851        gui.webHandler.sendPIREP(self._pirepSentCallback, pirep)
     1852
     1853    def _pirepSentCallback(self, returned, result):
     1854        """Callback for the PIREP sending result."""
     1855        gobject.idle_add(self._handlePIREPSent, returned, result)
     1856
     1857    def _handlePIREPSent(self, returned, result):
     1858        """Callback for the PIREP sending result."""
     1859        self._wizard.gui.endBusy()
     1860        secondaryMarkup = None
     1861        type = MESSAGETYPE_ERROR
     1862        if returned:
     1863            if result.success:
     1864                type = MESSAGETYPE_INFO
     1865                messageFormat = "The PIREP was sent successfully."
     1866                secondaryMarkup = "Await the thorough scrutiny from our PIREP correctors! :)"
     1867            elif result.alreadyFlown:
     1868                messageFormat = "The PIREP for this flight has already been sent!"
     1869                secondaryMarkup = "You may clear the old PIREP on the MAVA website."
     1870            elif result.notAvailable:
     1871                messageFormat = "This flight is not available anymore!"
     1872            else:
     1873                messageFormat = "The MAVA website returned with an unknown error."
     1874                secondaryMarkup = "See the debug log for more information."
     1875        else:
     1876            print "PIREP sending failed", result
     1877            messageFormat = "Could not send the PIREP to the MAVA website."
     1878            secondaryMarkup = "This can be a network problem, in which case\n" \
     1879                              "you may try again later. Or it can be a bug;\n" \
     1880                              "see the debug log for more information."
     1881       
     1882        dialog = gtk.MessageDialog(type = type, buttons = BUTTONSTYPE_OK,
     1883                                   message_format = messageFormat)
     1884        if secondaryMarkup is not None:
     1885            dialog.format_secondary_markup(secondaryMarkup)
     1886
     1887        dialog.run()
     1888        dialog.hide()
    17741889       
    17751890#-----------------------------------------------------------------------------
     
    17951910        self._routePage = RoutePage(self)
    17961911        self._pages.append(self._routePage)
    1797         self._pages.append(BriefingPage(self, True))
    1798         self._pages.append(BriefingPage(self, False))
     1912        self._departureBriefingPage = BriefingPage(self, True)
     1913        self._pages.append(self._departureBriefingPage)
     1914        self._arrivalBriefingPage = BriefingPage(self, False)
     1915        self._pages.append(self._arrivalBriefingPage)
    17991916        self._takeoffPage = TakeoffPage(self)
    18001917        self._pages.append(self._takeoffPage)
    18011918        self._landingPage = LandingPage(self)
    18021919        self._pages.append(self._landingPage)
    1803         self._pages.append(FinishPage(self))
     1920        self._finishPage = FinishPage(self)
     1921        self._pages.append(self._finishPage)
    18041922       
    18051923        maxWidth = 0
     
    18451963
    18461964    @property
     1965    def bookedFlight(self):
     1966        """Get the booked flight selected."""
     1967        return self._bookedFlight
     1968
     1969    @property
     1970    def cargoWeight(self):
     1971        """Get the calculated ZFW value."""
     1972        return self._payloadPage.cargoWeight
     1973
     1974    @property
    18471975    def zfw(self):
    18481976        """Get the calculated ZFW value."""
     
    18511979
    18521980    @property
     1981    def filedCruiseAltitude(self):
     1982        """Get the filed cruise altitude."""
     1983        return self._routePage.filedCruiseLevel * 100
     1984
     1985    @property
    18531986    def cruiseAltitude(self):
    18541987        """Get the cruise altitude."""
     
    18561989
    18571990    @property
     1991    def route(self):
     1992        """Get the route."""
     1993        return self._routePage.route
     1994
     1995    @property
     1996    def departureMETAR(self):
     1997        """Get the METAR of the departure airport."""
     1998        return self._departureBriefingPage.metar
     1999
     2000    @property
     2001    def arrivalMETAR(self):
     2002        """Get the METAR of the arrival airport."""
     2003        return self._arrivalBriefingPage.metar
     2004
     2005    @property
     2006    def departureRunway(self):
     2007        """Get the departure runway."""
     2008        return self._takeoffPage.runway
     2009
     2010    @property
     2011    def sid(self):
     2012        """Get the SID."""
     2013        return self._takeoffPage.sid
     2014
     2015    @property
    18582016    def v1(self):
    18592017        """Get the V1 speed."""
     
    18712029
    18722030    @property
     2031    def arrivalRunway(self):
     2032        """Get the arrival runway."""
     2033        return self._landingPage.runway
     2034
     2035    @property
     2036    def star(self):
     2037        """Get the STAR."""
     2038        return self._landingPage.star
     2039
     2040    @property
     2041    def transition(self):
     2042        """Get the transition."""
     2043        return self._landingPage.transition
     2044
     2045    @property
     2046    def approachType(self):
     2047        """Get the approach type."""
     2048        return self._landingPage.approachType
     2049
     2050    @property
    18732051    def vref(self):
    18742052        """Get the Vref speed."""
    18752053        return self._landingPage.vref
     2054
     2055    @property
     2056    def flightType(self):
     2057        """Get the flight type."""
     2058        return self._finishPage.flightType
     2059
     2060    @property
     2061    def online(self):
     2062        """Get whether the flight was online or not."""
     2063        return self._finishPage.online
    18762064
    18772065    def nextPage(self, finalize = True):
  • src/mlx/gui/gui.py

    r96 r97  
    120120
    121121    @property
     122    def logger(self):
     123        """Get the logger used by us."""
     124        return self._logger
     125       
     126    @property
    122127    def simulator(self):
    123128        """Get the simulator used by us."""
     
    130135
    131136    @property
     137    def bookedFlight(self):
     138        """Get the booked flight selected, if any."""
     139        return self._wizard.bookedFlight
     140
     141    @property
     142    def cargoWeight(self):
     143        """Get the cargo weight."""
     144        return self._wizard.cargoWeight
     145
     146    @property
    132147    def zfw(self):
    133148        """Get Zero-Fuel Weight calculated for the current flight."""
     
    135150       
    136151    @property
     152    def filedCruiseAltitude(self):
     153        """Get cruise altitude filed for the current flight."""
     154        return self._wizard.filedCruiseAltitude
     155       
     156    @property
    137157    def cruiseAltitude(self):
    138         """Get cruise altitude calculated for the current flight."""
     158        """Get cruise altitude set for the current flight."""
    139159        return self._wizard.cruiseAltitude
    140        
     160
     161    @property
     162    def route(self):
     163        """Get the flight route."""
     164        return self._wizard.route
     165
     166    @property
     167    def departureMETAR(self):
     168        """Get the METAR of the deprature airport."""
     169        return self._wizard.departureMETAR
     170       
     171    @property
     172    def arrivalMETAR(self):
     173        """Get the METAR of the deprature airport."""
     174        return self._wizard.arrivalMETAR
     175
     176    @property
     177    def departureRunway(self):
     178        """Get the name of the departure runway."""
     179        return self._wizard.departureRunway
     180       
     181    @property
     182    def sid(self):
     183        """Get the SID."""
     184        return self._wizard.sid
     185
    141186    @property
    142187    def v1(self):
     
    155200       
    156201    @property
     202    def arrivalRunway(self):
     203        """Get the arrival runway."""
     204        return self._wizard.arrivalRunway
     205
     206    @property
     207    def star(self):
     208        """Get the STAR."""
     209        return self._wizard.star
     210
     211    @property
     212    def transition(self):
     213        """Get the transition."""
     214        return self._wizard.transition
     215
     216    @property
     217    def approachType(self):
     218        """Get the approach type."""
     219        return self._wizard.approachType
     220
     221    @property
    157222    def vref(self):
    158223        """Get the Vref speed calculated for the flight."""
    159224        return self._wizard.vref
    160225       
     226    @property
     227    def flightType(self):
     228        """Get the flight type."""
     229        return self._wizard.flightType
     230
     231    @property
     232    def online(self):
     233        """Get whether the flight was online or not."""
     234        return self._wizard.online
     235
     236    @property
     237    def comments(self):
     238        """Get the comments."""
     239        return self._flightInfo.comments
     240
     241    @property
     242    def flightDefects(self):
     243        """Get the flight defects."""
     244        return self._flightInfo.flightDefects
     245
    161246    def run(self):
    162247        """Run the GUI."""
  • src/mlx/gui/info.py

    r93 r97  
    2323       
    2424        scroller = gtk.ScrolledWindow()
     25        # FIXME: these should be constants
    2526        scroller.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
    2627                            else gtk.POLICY_AUTOMATIC,
     
    117118        self.pack_start(self._delayAlignment, False, False, 8)
    118119
     120    @property
     121    def comments(self):
     122        """Get the comments."""
     123        buffer = self._comments.get_buffer()
     124        return text2unicode(buffer.get_text(buffer.get_start_iter(),
     125                                            buffer.get_end_iter(), True))
     126   
     127    @property
     128    def flightDefects(self):
     129        """Get the flight defects."""
     130        buffer = self._flightDefects.get_buffer()
     131        return text2unicode(buffer.get_text(buffer.get_start_iter(),
     132                                            buffer.get_end_iter(), True))
     133
    119134    def enable(self):
    120135        """Enable the flight info tab."""
     
    144159        self._weatherProblems.set_active(False)
    145160        self._personalReasons.set_active(False)
    146 
  • src/mlx/logger.py

    r96 r97  
    44
    55import const
     6import util
    67
    78import sys
     
    3233        self._lines = []
    3334        self._faults = {}
     35        self._faultLineIndexes = []
    3436        self._output = output
    3537
    36     @staticmethod
    37     def _getTimeStr(timestamp):
    38         """Get the string representation of the given timestamp."""
    39         return time.strftime("%H:%M:%S", time.gmtime(timestamp))
     38    @property
     39    def lines(self):
     40        """Get the lines of the log."""
     41        return self._lines
     42
     43    @property
     44    def faultLineIndexes(self):
     45        """Get the array of the indexes of the log line that contains a
     46        fault."""
     47        return self._faultLineIndexes
    4048
    4149    def reset(self):
     
    4553        self._lines = []
    4654        self._faults.clear()
     55        self._faultLineIndexes = []
    4756               
    4857    def message(self, timestamp, msg):
    4958        """Put a simple textual message into the log with the given timestamp."""
    50         timeStr = Logger._getTimeStr(timestamp)
     59        timeStr = util.getTimestampString(timestamp)
    5160        return self._logLine(msg, timeStr)
    5261
     
    7887        self._faults[faultID] = score
    7988        if score==Logger.NO_GO_SCORE:
    80             self.message(timestamp, "%s (NO GO)" % (what))
     89            lineIndex = self.message(timestamp, "%s (NO GO)" % (what))
    8190        else:
    82             self.message(timestamp, "%s (%.1f)" % (what, score))
     91            lineIndex = self.message(timestamp, "%s (%.1f)" % (what, score))
     92        self._faultLineIndexes.append(lineIndex)
    8393
    8494    def noGo(self, faultID, timestamp, what):
  • src/mlx/util.py

    r89 r97  
    22
    33import math
     4import time
    45
    56#------------------------------------------------------------------------------
     
    7576#------------------------------------------------------------------------------
    7677
     78def getTimestampString(timestamp):
     79    """Get the string representation of the given timestamp."""
     80    return time.strftime("%H:%M:%S", time.gmtime(timestamp))
     81
     82#------------------------------------------------------------------------------
     83
    7784def getTimeIntervalString(seconds):
    7885    """Get a more human-friendly representation of the given time interval
     
    8188    minutes = int((seconds / 60) % 60)
    8289    seconds = int(seconds % 60)
    83     return "%d:%02d:%02d" % (hours, minutes, seconds)
     90    return "%02d:%02d:%02d" % (hours, minutes, seconds)
    8491
    8592#------------------------------------------------------------------------------
  • src/mlx/web.py

    r88 r97  
    44
    55import const
     6import util
    67
    78import threading
     
    482483#------------------------------------------------------------------------------
    483484
     485class SendPIREP(Request):
     486    """A request to send a PIREP to the MAVA website."""
     487    _flightTypes = { const.FLIGHTTYPE_SCHEDULED : "SCHEDULED",
     488                     const.FLIGHTTYPE_OLDTIMER : "OT",
     489                     const.FLIGHTTYPE_VIP : "VIP",
     490                     const.FLIGHTTYPE_CHARTER : "CHARTER" }
     491
     492    _latin2Encoder = codecs.getencoder("iso-8859-2")
     493
     494    def __init__(self, callback, pirep):
     495        """Construct the request for the given PIREP."""
     496        super(SendPIREP, self).__init__(callback)
     497        self._pirep = pirep
     498
     499    def run(self):
     500        """Perform the retrieval opf the METARs."""
     501        url = "http://www.virtualairlines.hu/malevacars.php"
     502
     503        pirep = self._pirep
     504
     505        data = {}
     506        data["acarsdata"] = pirep.getACARSText()
     507
     508        bookedFlight = pirep.bookedFlight
     509        data["foglalas_id"] = bookedFlight.id
     510        data["repdate"] = bookedFlight.departureTime.date().strftime("%Y-%m-%d")
     511        data["fltnum"] = bookedFlight.callsign
     512        data["depap"] = bookedFlight.departureICAO
     513        data["arrap"] = bookedFlight.arrivalICAO
     514        data["pass"] = str(bookedFlight.numPassengers)
     515        data["crew"] = str(bookedFlight.numCrew)
     516        data["cargo"] = str(pirep.cargoWeight)
     517        data["bag"] = str(bookedFlight.bagWeight)
     518        data["mail"] = str(bookedFlight.mailWeight)
     519       
     520        data["flttype"] = SendPIREP._flightTypes[pirep.flightType]
     521        data["onoff"] = "1" if pirep.online else "0"
     522        data["bt_dep"] = util.getTimestampString(pirep.blockTimeStart)
     523        data["bt_arr"] = util.getTimestampString(pirep.blockTimeEnd)
     524        data["bt_dur"] = util.getTimeIntervalString(pirep.blockTimeEnd -
     525                                                    pirep.blockTimeStart)
     526        data["ft_dep"] = util.getTimestampString(pirep.flightTimeStart)
     527        data["ft_arr"] = util.getTimestampString(pirep.flightTimeEnd)
     528        data["ft_dur"] = util.getTimeIntervalString(pirep.flightTimeEnd -
     529                                                    pirep.flightTimeStart)
     530        data["timecomm"] = pirep.getTimeComment()
     531        data["fuel"] = "%.0f" % (pirep.fuelUsed,)
     532        data["dep_rwy"] = pirep.departureRunway
     533        data["arr_rwy"] = pirep.arrivalRunway
     534        data["wea_dep"] = pirep.departureMETAR
     535        data["wea_arr"] = pirep.arrivalMETAR
     536        data["alt"] = "FL%.0f" % (pirep.filedCruiseAltitude/100.0,)
     537        if pirep.filedCruiseAltitude!=pirep.cruiseAltitude:
     538            data["mod_alt"] = "FL%.0f" % (pirep.cruiseAltitude/100.0,)
     539        else:
     540            data["mod_alt"] = ""
     541        data["sid"] = pirep.sid
     542        data["navroute"] = pirep.route
     543        data["star"] = pirep.getSTAR()
     544        data["aprtype"] = pirep.approachType
     545        data["diff"] = "2"
     546        data["comment"] = SendPIREP._latin2Encoder(pirep.comments)[0]
     547        data["flightdefect"] = SendPIREP._latin2Encoder(pirep.flightDefects)[0]
     548        data["kritika"] = pirep.getRatingText()
     549        data["flightRating"] = "%.1f" % (max(0.0, pirep.rating),)
     550        data["distance"] = "%.3f" % (pirep.flownDistance,)
     551        data["insdate"] = datetime.date.today().strftime("%Y-%m-%d")
     552
     553        f = urllib2.urlopen(url, urllib.urlencode(data), timeout = 10.0)
     554        try:
     555            result = Result()
     556            line = f.readline().strip()
     557            print "PIREP result from website:", line
     558            result.success = line=="OK"
     559            result.alreadyFlown = line=="MARVOLT"
     560            result.notAvailable = line=="NOMORE"
     561        finally:
     562            f.close()
     563
     564        return result   
     565
     566#------------------------------------------------------------------------------
     567
    484568class Handler(threading.Thread):
    485569    """The handler for the web services.
     
    515599        """Get the METARs for the given airports."""
    516600        self._addRequest(GetMETARs(callback, airports))
     601
     602    def sendPIREP(self, callback, pirep):
     603        """Send the given PIREP."""
     604        self._addRequest(SendPIREP(callback, pirep))
    517605       
    518606    def run(self):
Note: See TracChangeset for help on using the changeset viewer.