Changeset 1044:988bfea3e8db for src/mlx/web.py
- Timestamp:
- 04/04/22 13:59:17 (2 years ago)
- Branch:
- python3
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/mlx/web.py
r1034 r1044 2 2 from . import const 3 3 from . import util 4 from .rpc import Registration 4 from .rpc import Registration, BookedFlight 5 5 from . import rpc 6 6 from . import rpccommon … … 54 54 return line 55 55 56 #---------------------------------------------------------------------------------------57 58 class BookedFlight(object):59 """A flight that was booked."""60 TYPECODE2TYPE = { "B736" : const.AIRCRAFT_B736,61 "B737" : const.AIRCRAFT_B737,62 "B738" : const.AIRCRAFT_B738,63 "B73H" : const.AIRCRAFT_B738C,64 "B732" : const.AIRCRAFT_B732,65 "B733" : const.AIRCRAFT_B733,66 "B734" : const.AIRCRAFT_B734,67 "B735" : const.AIRCRAFT_B735,68 "DH8D" : const.AIRCRAFT_DH8D,69 "B762" : const.AIRCRAFT_B762,70 "B763" : const.AIRCRAFT_B763,71 "CRJ2" : const.AIRCRAFT_CRJ2,72 "F70" : const.AIRCRAFT_F70,73 "LI2" : const.AIRCRAFT_DC3,74 "T134" : const.AIRCRAFT_T134,75 "T154" : const.AIRCRAFT_T154,76 "YK40" : const.AIRCRAFT_YK40,77 "B462" : const.AIRCRAFT_B462,78 "IL62" : const.AIRCRAFT_IL62 }79 80 TYPE2TYPECODE = { const.AIRCRAFT_B736 : "B736",81 const.AIRCRAFT_B737 : "B737",82 const.AIRCRAFT_B738 : "B738",83 const.AIRCRAFT_B738C : "B73H",84 const.AIRCRAFT_B732 : "B732",85 const.AIRCRAFT_B733 : "B733",86 const.AIRCRAFT_B734 : "B734",87 const.AIRCRAFT_B735 : "B735",88 const.AIRCRAFT_DH8D : "DH8D",89 const.AIRCRAFT_B762 : "B762",90 const.AIRCRAFT_B763 : "B763",91 const.AIRCRAFT_CRJ2 : "CRJ2",92 const.AIRCRAFT_F70 : "F70",93 const.AIRCRAFT_DC3 : "LI2",94 const.AIRCRAFT_T134 : "T134",95 const.AIRCRAFT_T154 : "T155",96 const.AIRCRAFT_YK40 : "YK40",97 const.AIRCRAFT_B462 : "B462",98 const.AIRCRAFT_IL62 : "IL62" }99 100 checkFlightTypes = [ const.AIRCRAFT_B736, const.AIRCRAFT_B737,101 const.AIRCRAFT_B738, const.AIRCRAFT_DH8D ]102 103 STATUS_BOOKED = 1104 105 STATUS_REPORTED = 2106 107 STATUS_ACCEPTED = 3108 109 STATUS_REJECTED = 4110 111 @staticmethod112 def getDateTime(date, time):113 """Get a datetime object from the given textual date and time."""114 return datetime.datetime.strptime(date + " " + time,115 "%Y-%m-%d %H:%M:%S")116 117 @staticmethod118 def forCheckFlight(aircraftType):119 """Create a booked flight for a check flight with the given aircraft120 type."""121 flight = BookedFlight()122 123 flight.departureICAO = "LHBP"124 flight.arrivalICAO = "LHBP"125 126 flight.aircraftType = aircraftType127 flight.aircraftTypeName = BookedFlight.TYPE2TYPECODE[aircraftType]128 129 # FIXME: perhaps find one for the type130 flight.tailNumber = "HA-CHK"131 flight.callsign = "HA-CHK"132 133 flight.numPassengers = 0134 flight.numCrew = 2135 flight.bagWeight = 0136 flight.cargoWeight = 0137 flight.mailWeight = 0138 flight.route = "DCT"139 140 t = datetime.datetime.now() + datetime.timedelta(minutes = 20)141 flight.departureTime = datetime.datetime(t.year, t.month, t.day,142 t.hour, t.minute)143 t = flight.departureTime + datetime.timedelta(minutes = 30)144 flight.arrivalTime = datetime.datetime(t.year, t.month, t.day,145 t.hour, t.minute)146 147 return flight148 149 @staticmethod150 def _convertFlightType(ft):151 """Convert the in-database flight-type to one of our constants."""152 ft = int(ft)153 if ft==0:154 return const.FLIGHTTYPE_SCHEDULED155 elif ft==1:156 return const.FLIGHTTYPE_VIP157 elif ft==2:158 return const.FLIGHTTYPE_CHARTER159 else:160 return const.FLIGHTTYPE_SCHEDULED161 162 def __init__(self, id = None):163 """Construct a booked flight with the given ID."""164 self.id = id165 166 @property167 def status(self):168 """Get the status of the flight.169 170 For web-based flights this is always STATUS_BOOKED."""171 return BookedFlight.STATUS_BOOKED172 173 def readFromWeb(self, f):174 """Read the data of the flight from the web via the given file175 object."""176 self.callsign = readline(f)177 178 date = readline(f)179 print("web.BookedFlight.readFromWeb: date:", date)180 if date=="0000-00-00": date = "0001-01-01"181 182 self.departureICAO = readline(f)183 self.arrivalICAO = readline(f)184 185 self._readAircraftType(f)186 self.tailNumber = readline(f)187 self.numPassengers = int(readline(f))188 self.numCrew = int(readline(f))189 self.bagWeight = int(readline(f))190 self.cargoWeight = int(readline(f))191 self.mailWeight = int(readline(f))192 self.route = readline(f)193 194 departureTime = readline(f)195 self.departureTime = BookedFlight.getDateTime(date, departureTime)196 197 arrivalTime = readline(f)198 self.arrivalTime = BookedFlight.getDateTime(date, arrivalTime)199 if self.arrivalTime<self.departureTime:200 self.arrivalTime += datetime.timedelta(days = 1)201 202 if not readline(f)==".NEXT.":203 raise Exception("Invalid line in flight data")204 205 def readFromFile(self, f):206 """Read the data of the flight from a file via the given file207 object."""208 date = None209 departureTime = None210 arrivalTime = None211 212 line = f.readline()213 lineNumber = 0214 while line:215 lineNumber += 1216 line = line.strip()217 218 hashIndex = line.find("#")219 if hashIndex>=0: line = line[:hashIndex]220 if line:221 equalIndex = line.find("=")222 lineOK = equalIndex>0223 224 if lineOK:225 key = line[:equalIndex].strip()226 value = line[equalIndex+1:].strip().replace("\:", ":")227 228 lineOK = key and value229 230 if lineOK:231 if key=="callsign": self.callsign = value232 elif key=="date": date = value233 elif key=="dep_airport": self.departureICAO = value234 elif key=="dest_airport": self.arrivalICAO = value235 elif key=="planecode": self.aircraftType = \236 self._decodeAircraftType(value)237 elif key=="planetype": self.aircraftTypeName = value238 elif key=="tail_nr": self.tailNumber = value239 elif key=="passenger": self.numPassengers = int(value)240 elif key=="crew": self.numCrew = int(value)241 elif key=="bag": self.bagWeight = int(value)242 elif key=="cargo": self.cargoWeight = int(value)243 elif key=="mail": self.mailWeight = int(value)244 elif key=="flight_route": self.route = value245 elif key=="departure_time": departureTime = value246 elif key=="arrival_time": arrivalTime = value247 elif key=="foglalas_id":248 self.id = None if value=="0" else value249 else: lineOK = False250 251 if not lineOK:252 print("web.BookedFlight.readFromFile: line %d is invalid" % \253 (lineNumber,))254 255 line = f.readline()256 257 if date is not None:258 if departureTime is not None:259 self.departureTime = BookedFlight.getDateTime(date,260 departureTime)261 if arrivalTime is not None:262 self.arrivalTime = BookedFlight.getDateTime(date,263 arrivalTime)264 265 d = dir(self)266 for attribute in ["callsign", "departureICAO", "arrivalICAO",267 "aircraftType", "tailNumber",268 "numPassengers", "numCrew",269 "bagWeight", "cargoWeight", "mailWeight",270 "route", "departureTime", "arrivalTime"]:271 if attribute not in d:272 raise Exception("Attribute %s could not be read" % (attribute,))273 274 if "aircraftTypeName" not in d:275 self.aircraftTypeName = \276 BookedFlight.TYPE2TYPECODE[self.aircraftType]277 278 def setupFromPIREPData(self, pirepData):279 """Setup the booked flight from the given PIREP data."""280 bookedFlightData = pirepData["bookedFlight"]281 282 self.callsign = bookedFlightData["callsign"]283 284 date = bookedFlightData["date"]285 286 departureTime = bookedFlightData["departureTime"]287 self.departureTime = BookedFlight.getDateTime(date, departureTime)288 289 arrivalTime = bookedFlightData["arrivalTime"]290 self.arrivalTime = BookedFlight.getDateTime(date, arrivalTime)291 if self.arrivalTime<self.departureTime:292 self.arrivalTime += datetime.timedelta(days = 1)293 294 self.departureICAO = bookedFlightData["departureICAO"]295 self.arrivalICAO = bookedFlightData["arrivalICAO"]296 297 self.aircraftType = \298 self._decodeAircraftType(bookedFlightData["aircraftType"])299 self.tailNumber = bookedFlightData["tailNumber"]300 self.numPassengers = int(bookedFlightData["numPassengers"])301 self.numChildren = int(bookedFlightData["numChildren"])302 self.numInfants = int(bookedFlightData["numInfants"])303 self.maxPassengers = int(bookedFlightData["maxPassengers"])304 self.numCockpitCrew = int(bookedFlightData["numCockpitCrew"])305 self.numCabinCrew = int(bookedFlightData["numCabinCrew"])306 self.bagWeight = int(bookedFlightData["bagWeight"])307 self.cargoWeight = int(bookedFlightData["cargoWeight"])308 self.mailWeight = int(bookedFlightData["mailWeight"])309 self.route = bookedFlightData["route"]310 self.flightType = BookedFlight._convertFlightType(bookedFlightData["flightType"])311 312 def writeIntoFile(self, f):313 """Write the flight into a file."""314 print("callsign=%s" % (self.callsign,), file=f)315 date = self.departureTime.date()316 print("date=%04d-%02d-%0d" % (date.year, date.month, date.day), file=f)317 print("dep_airport=%s" % (self.departureICAO,), file=f)318 print("dest_airport=%s" % (self.arrivalICAO,), file=f)319 print("planecode=%s" % \320 (BookedFlight.TYPE2TYPECODE[self.aircraftType],), file=f)321 print("planetype=%s" % (self.aircraftTypeName,), file=f)322 print("tail_nr=%s" % (self.tailNumber,), file=f)323 print("passenger=%d" % (self.numPassengers,), file=f)324 print("crew=%d" % (self.numCrew,), file=f)325 print("bag=%d" % (self.bagWeight,), file=f)326 print("cargo=%d" % (self.cargoWeight,), file=f)327 print("mail=%d" % (self.mailWeight,), file=f)328 print("flight_route=%s" % (self.route,), file=f)329 departureTime = self.departureTime330 print("departure_time=%02d\\:%02d\\:%02d" % \331 (departureTime.hour, departureTime.minute, departureTime.second), file=f)332 arrivalTime = self.arrivalTime333 print("arrival_time=%02d\\:%02d\\:%02d" % \334 (arrivalTime.hour, arrivalTime.minute, arrivalTime.second), file=f)335 print("foglalas_id=%s" % ("0" if self.id is None else self.id,), file=f)336 337 def _readAircraftType(self, f):338 """Read the aircraft type from the given file."""339 line = readline(f)340 typeCode = line[:3]341 self.aircraftType = self._decodeAircraftType(typeCode)342 self.aircraftTypeName = line[3:]343 344 def _decodeAircraftType(self, typeCode):345 """Decode the aircraft type from the given typeCode."""346 if typeCode in self.TYPECODE2TYPE:347 return self.TYPECODE2TYPE[typeCode]348 else:349 raise Exception("Invalid aircraft type code: '" + typeCode + "'")350 351 def __repr__(self):352 """Get a representation of the flight."""353 s = "<Flight: %s-%s, %s, %s-%s," % (self.departureICAO,354 self.arrivalICAO,355 self.route,356 self.departureTime, self.arrivalTime)357 s += " %d %s," % (self.aircraftType, self.tailNumber)358 s += " pax=%d, crew=%d, bag=%d, cargo=%d, mail=%d" % \359 (self.numPassengers, self.numCrew,360 self.bagWeight, self.cargoWeight, self.mailWeight)361 s += ">"362 return s363 364 56 #------------------------------------------------------------------------------ 365 57 … … 769 461 #------------------------------------------------------------------------------ 770 462 771 class Login(Request):772 """A login request."""773 iso88592decoder = codecs.getdecoder("iso-8859-2")774 775 def __init__(self, callback, pilotID, password):776 """Construct the login request with the given pilot ID and777 password."""778 super(Login, self).__init__(callback)779 780 self._pilotID = pilotID781 self._password = password782 783 def run(self):784 """Perform the login request."""785 md5 = hashlib.md5()786 md5.update(self._pilotID)787 pilotID = md5.hexdigest()788 789 md5 = hashlib.md5()790 md5.update(self._password)791 password = md5.hexdigest()792 793 url = MAVA_BASE_URL + "/leker2.php?pid=%s&psw=%s" % (pilotID, password)794 795 result = Result()796 797 f = urllib.request.urlopen(url, timeout = 10.0)798 799 status = readline(f)800 result.loggedIn = status == ".OK."801 802 if result.loggedIn:803 result.pilotID = self._pilotID804 result.password = self._password805 result.rank = "FO"806 result.flights = []807 808 result.pilotName = self.iso88592decoder(readline(f))[0]809 result.exams = readline(f)810 811 while True:812 line = readline(f)813 if not line or line == "#ENDPIREP": break814 815 flight = BookedFlight(line)816 flight.readFromWeb(f)817 result.flights.append(flight)818 819 result.flights.sort(key = lambda flight: flight.departureTime)820 821 f.close()822 823 return result824 825 #------------------------------------------------------------------------------826 827 463 class LoginRPC(RPCRequest): 828 464 """An RPC-based login request.""" … … 839 475 result.types = loginResult[2] 840 476 result.password = password 477 result.fleet = client.getFleet() 841 478 flights = client.getFlights() 842 479 result.flights = flights[0] … … 893 530 #------------------------------------------------------------------------------ 894 531 895 class GetFleet(Request):896 """Request to get the fleet from the website."""897 898 def __init__(self, callback):899 """Construct the fleet request."""900 super(GetFleet, self).__init__(callback)901 902 def run(self):903 """Perform the login request."""904 url = MAVA_BASE_URL + "/onlinegates_get.php"905 906 f = urllib.request.urlopen(url, timeout = 10.0)907 result = Result()908 result.fleet = Fleet(f)909 f.close()910 911 return result912 913 #------------------------------------------------------------------------------914 915 532 class GetFleetRPC(RPCRequest): 916 533 """Request to get the fleet from the website using RPC.""" … … 924 541 925 542 result.fleet = self._client.getFleet() 926 927 return result928 929 #------------------------------------------------------------------------------930 931 class UpdatePlane(Request):932 """Update the status of one of the planes in the fleet."""933 def __init__(self, callback, tailNumber, status, gateNumber = None):934 """Construct the request."""935 super(UpdatePlane, self).__init__(callback)936 self._tailNumber = tailNumber937 self._status = status938 self._gateNumber = gateNumber939 940 def run(self):941 """Perform the plane update."""942 url = MAVA_BASE_URL + "/onlinegates_set.php"943 944 status = Plane.status2str(self._status)945 946 gateNumber = self._gateNumber if self._gateNumber else ""947 948 data = urllib.parse.urlencode([("lajstrom", self._tailNumber),949 ("status", status),950 ("kapu", gateNumber)])951 952 f = urllib.request.urlopen(url, data, timeout = 10.0)953 line = readline(f)954 955 result = Result()956 result.success = line == "OK"957 543 958 544 return result … … 1095 681 #------------------------------------------------------------------------------ 1096 682 1097 class SendPIREP(Request):1098 """A request to send a PIREP to the MAVA website."""1099 _latin2Encoder = codecs.getencoder("iso-8859-2")1100 1101 def __init__(self, callback, pirep):1102 """Construct the sending of the PIREP."""1103 super(SendPIREP, self).__init__(callback)1104 self._pirep = pirep1105 1106 def run(self):1107 """Perform the sending of the PIREP."""1108 url = MAVA_BASE_URL + "/malevacars.php"1109 1110 pirep = self._pirep1111 1112 data = {}1113 data["acarsdata"] = SendPIREP._latin2Encoder(pirep.getACARSText())[0]1114 1115 bookedFlight = pirep.bookedFlight1116 data["foglalas_id"] = bookedFlight.id1117 data["repdate"] = bookedFlight.departureTime.date().strftime("%Y-%m-%d")1118 data["fltnum"] = bookedFlight.callsign1119 data["depap"] = bookedFlight.departureICAO1120 data["arrap"] = bookedFlight.arrivalICAO1121 data["pass"] = str(pirep.numPassengers)1122 data["crew"] = str(pirep.numCrew)1123 data["cargo"] = str(pirep.cargoWeight)1124 data["bag"] = str(pirep.bagWeight)1125 data["mail"] = str(pirep.mailWeight)1126 1127 data["flttype"] = pirep.flightTypeText1128 data["onoff"] = "1" if pirep.online else "0"1129 data["bt_dep"] = util.getTimestampString(pirep.blockTimeStart)1130 data["bt_arr"] = util.getTimestampString(pirep.blockTimeEnd)1131 data["bt_dur"] = util.getTimeIntervalString(pirep.blockTimeEnd -1132 pirep.blockTimeStart)1133 data["ft_dep"] = util.getTimestampString(pirep.flightTimeStart)1134 data["ft_arr"] = util.getTimestampString(pirep.flightTimeEnd)1135 data["ft_dur"] = util.getTimeIntervalString(pirep.flightTimeEnd -1136 pirep.flightTimeStart)1137 data["timecomm"] = pirep.getTimeComment()1138 data["fuel"] = "%.2f" % (pirep.fuelUsed,)1139 data["dep_rwy"] = pirep.departureRunway1140 data["arr_rwy"] = pirep.arrivalRunway1141 data["wea_dep"] = pirep.departureMETAR1142 data["wea_arr"] = pirep.arrivalMETAR1143 data["alt"] = "FL%.0f" % (pirep.filedCruiseAltitude/100.0,)1144 if pirep.filedCruiseAltitude!=pirep.cruiseAltitude:1145 data["mod_alt"] = "FL%.0f" % (pirep.cruiseAltitude/100.0,)1146 else:1147 data["mod_alt"] = ""1148 data["sid"] = pirep.sid1149 data["navroute"] = pirep.route1150 data["star"] = pirep.getSTAR()1151 data["aprtype"] = pirep.approachType1152 data["diff"] = "2"1153 data["comment"] = SendPIREP._latin2Encoder(pirep.comments)[0]1154 data["flightdefect"] = SendPIREP._latin2Encoder(pirep.flightDefects)[0]1155 data["kritika"] = pirep.getRatingText()1156 data["flightrating"] = "%.1f" % (max(0.0, pirep.rating),)1157 data["distance"] = "%.3f" % (pirep.flownDistance,)1158 data["insdate"] = datetime.date.today().strftime("%Y-%m-%d")1159 1160 postData = urllib.parse.urlencode(data)1161 f = urllib.request.urlopen(url, postData, timeout = 10.0)1162 try:1163 result = Result()1164 line = f.readline().strip()1165 print("PIREP result from website:", line)1166 result.success = line=="OK"1167 result.alreadyFlown = line=="MARVOLT"1168 result.notAvailable = line=="NOMORE"1169 finally:1170 f.close()1171 1172 return result1173 #------------------------------------------------------------------------------1174 1175 683 class SendPIREPRPC(RPCRequest): 1176 684 """A request to send a PIREP to the MAVA website via the RPC interface.""" … … 1192 700 result.alreadyFlown = resultCode==rpc.Client.RESULT_FLIGHT_ALREADY_REPORTED 1193 701 result.notAvailable = resultCode==rpc.Client.RESULT_FLIGHT_NOT_EXISTS 1194 1195 return result1196 1197 #------------------------------------------------------------------------------1198 1199 class SendACARS(Request):1200 """A request to send an ACARS to the MAVA website."""1201 _latin2Encoder = codecs.getencoder("iso-8859-2")1202 1203 def __init__(self, callback, acars):1204 """Construct the request for the given PIREP."""1205 super(SendACARS, self).__init__(callback)1206 self._acars = acars1207 1208 def run(self):1209 """Perform the sending of the ACARS."""1210 print("Sending the online ACARS")1211 1212 url = MAVA_BASE_URL + "/acars2/acarsonline.php"1213 1214 acars = self._acars1215 bookedFlight = acars.bookedFlight1216 1217 data = {}1218 data["pid"] = acars.pid1219 data["pilot"] = SendACARS._latin2Encoder(acars.pilotName)[0]1220 1221 data["pass"] = str(bookedFlight.numPassengers)1222 data["callsign"] = bookedFlight.callsign1223 data["airplane"] = bookedFlight.aircraftTypeName1224 data["from"] = bookedFlight.departureICAO1225 data["to"] = bookedFlight.arrivalICAO1226 data["lajstrom"] = bookedFlight.tailNumber1227 1228 data["block_time"] = acars.getBlockTimeText()1229 data["longitude"] = str(acars.state.longitude)1230 data["latitude"] = str(acars.state.latitude)1231 data["altitude"] = str(acars.state.altitude)1232 data["speed"] = str(acars.state.groundSpeed)1233 1234 data["event"] = acars.getEventText()1235 1236 f = urllib.request.urlopen(url, urllib.parse.urlencode(data), timeout = 10.0)1237 try:1238 result = Result()1239 finally:1240 f.close()1241 702 1242 703 return result … … 1320 781 print("pirepData:", pirepData) 1321 782 1322 bookedFlight = BookedFlight( self._flightID)783 bookedFlight = BookedFlight(id = self._flightID) 1323 784 bookedFlight.setupFromPIREPData(pirepData) 1324 785 … … 1437 898 def login(self, callback, pilotID, password): 1438 899 """Enqueue a login request.""" 1439 request = \ 1440 LoginRPC(self._rpcClient, callback, pilotID, password) \ 1441 if self._config.useRPC else Login(callback, pilotID, password) 900 request = LoginRPC(self._rpcClient, callback, pilotID, password) 1442 901 1443 902 self._addRequest(request) … … 1449 908 def getFleet(self, callback): 1450 909 """Enqueue a fleet retrieval request.""" 1451 request = \ 1452 GetFleetRPC(self._rpcClient, callback,) if self._config.useRPC \ 1453 else GetFleet(callback) 910 request = GetFleetRPC(self._rpcClient, callback,) 1454 911 self._addRequest(request) 1455 912 1456 913 def updatePlane(self, callback, tailNumber, status, gateNumber = None): 1457 914 """Update the status of the given plane.""" 1458 request = \ 1459 UpdatePlaneRPC(self._rpcClient, callback, 1460 tailNumber, status, gateNumber) \ 1461 if self._config.useRPC \ 1462 else UpdatePlane(callback, tailNumber, status, gateNumber) 915 request = UpdatePlaneRPC(self._rpcClient, callback, 916 tailNumber, status, gateNumber) 1463 917 self._addRequest(request) 1464 918 … … 1473 927 def sendPIREP(self, callback, pirep, update = False): 1474 928 """Send the given PIREP.""" 1475 request = \ 1476 SendPIREPRPC(self._rpcClient, callback, pirep, update) \ 1477 if self._config.useRPC else SendPIREP(callback, pirep) 929 request = SendPIREPRPC(self._rpcClient, callback, pirep, update) 1478 930 self._addRequest(request) 1479 931 1480 932 def sendACARS(self, callback, acars): 1481 933 """Send the given ACARS""" 1482 request = \ 1483 SendACARSRPC(self._rpcClient, callback, acars) if self._config.useRPC \ 1484 else SendACARS(callback, acars) 934 request = SendACARSRPC(self._rpcClient, callback, acars) 1485 935 self._addRequest(request) 1486 936
Note:
See TracChangeset
for help on using the changeset viewer.