def resetData(self): # FPL.TIME_OF_DEP dep = self.fpl[FPL.TIME_OF_DEP] self.depTime_enable.setChecked(dep != None) if dep == None: dep = now() self.depTime_edit.setDateTime( QDateTime(dep.year, dep.month, dep.day, dep.hour, dep.minute)) # FPL.EET eet = self.fpl[FPL.EET] self.EET_enable.setChecked(eet != None) if eet != None: minutes = int(eet.total_seconds() / 60 + .5) self.EETh_edit.setValue(minutes // 60) self.EETmin_edit.setValue(minutes % 60) # ICAO_ALT self.altAirportPicker_widget.setEditText( some(self.fpl[FPL.ICAO_ALT], '')) # SOULS souls = self.fpl[FPL.SOULS] self.soulsOnBoard_enable.setChecked(souls != None) if souls != None: self.soulsOnBoard_edit.setValue(souls) # ONLINE COMMENTS self.viewOnlineComments_button.setEnabled( self.fpl.onlineComments() != []) SharedDetailSheet.resetData(self)
def changeFplOnlineStatus(self, new_status): t = now() if new_status == FPL.OPEN: text = 'Do you want also to update departure time with the current date & time below?\n%s, %s' % ( datestr(t), timestr(t)) text += '\n\nWARNING: Answering "yes" or "no" will open the flight plan online.' button = QMessageBox.question( self, 'Open FPL', text, buttons=(QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)) if button == QMessageBox.Yes: self.depTime_edit.setDateTime( QDateTime(t.year, t.month, t.day, t.hour, t.minute)) ok = button != QMessageBox.Cancel elif new_status == FPL.CLOSED: ok = yesNo_question(self, 'Close FPL', 'Time is %s.' % timestr(t), 'This will close the flight plan online. OK?') if ok: try: settings.session_manager.changeFplStatus(self.fpl, new_status) except FplError as err: QMessageBox.critical(self, 'FPL open/close error', str(err)) self.updateOnlineStatusBox()
def addNotification(self, t, msg, dbl_click_function): position = self.rowCount() self.beginInsertRows(QModelIndex(), position, position) self.history.insert(position, Notification(t, now(), msg, dbl_click_function)) self.endInsertRows() return True
def auto_print_strip_reason(fpl): ''' Returns reason to print if strip should be auto-printed from FPL; None otherwise ''' if fpl.status() == FPL.CLOSED or fpl.strip_auto_printed \ or settings.auto_print_strips_IFR_only and fpl[FPL.FLIGHT_RULES] != 'IFR' \ or env.airport_data == None or env.linkedStrip(fpl) != None: return None present_time = now() ok_reason = None if settings.auto_print_strips_include_DEP: # check DEP time dep = fpl[FPL.TIME_OF_DEP] if dep != None and fpl[ FPL. ICAO_DEP] == env.airport_data.navpoint.code: # we know: fpl.status() != FPL.CLOSED if dep - settings.auto_print_strips_anticipation <= present_time <= dep: ok_reason = 'departure due ' + rel_datetime_str(dep) if ok_reason == None and settings.auto_print_strips_include_ARR: # check ARR time eta = fpl.ETA() if eta != None and fpl[ FPL.ICAO_ARR] == env.airport_data.navpoint.code and fpl.status( ) == FPL.OPEN: if eta - settings.auto_print_strips_anticipation <= present_time <= eta: ok_reason = 'arrival due ' + rel_datetime_str(eta) return ok_reason
def get_declination(earth_location): today = now() try: q_items = { 'startYear': today.year, 'startMonth': today.month, 'startDay': today.day, 'resultFormat': 'xml', 'lon1Hemisphere': 'EW'[earth_location.lon < 0], 'lon1': abs(earth_location.lon), 'lat1Hemisphere': 'NS'[earth_location.lat < 0], 'lat1': abs(earth_location.lat), 'browserRequest': 'false' } #DEBUG print('%s?%s' % (decl_base_location, urlencode(q_items))) response = open_URL('%s?%s' % (decl_base_location, urlencode(q_items))) xml = ElementTree.fromstring(response) if xml.tag == 'maggridresult': res_elt = xml.find('result') if res_elt != None: decl = float(res_elt.find('declination').text) return decl except URLError: print('Could not obtain declination from NOAA website.') except timeout: print('NOAA declination request timed out.') except ElementTree.ParseError: print('Parse error while reading NOAA data.')
def checkAckTimeout(self): if settings.CPDLC_ACK_timeout != None and self.expecting: last_msg = self.lastMsg() if last_msg.isFromMe() and now() - last_msg.timeStamp() >= settings.CPDLC_ACK_timeout: self.timed_out = True self.statusChanged.emit() signals.cpdlcProblem.emit(self.acftCallsign(), 'Answer timed out')
def resumeSession(self): if self.isRunning() and self.simulation_paused_at != None: pause_delay = now() - self.simulation_paused_at for acft in self.getAircraft(): acft.moveHistoryTimesForward(pause_delay) self.session_ticker.start_stopOnZero(solo_ticker_interval) self.simulation_paused_at = None signals.sessionResumed.emit()
def mkWeather(station, wind='00000KT', vis=9999, clouds='NSC', qnh=1013): metar = '%s %s %s' % (station, METAR_time_str(now()), wind) if vis >= 9999 and clouds == 'NSC': metar += ' CAVOK' else: metar += ' %04d %s' % (min(vis, 9999), clouds) metar += ' 15/05' metar += ' Q%d' % qnh return Weather(metar + '=')
def resumeSession(self): pause_delay = now() - self.simulation_paused_at for acft in self.aircraft_list: acft.moveHistoryTimesForward(pause_delay) self.simulation_paused_at = None self.session_ticker.start_stopOnZero(teacher_ticker_interval) signals.sessionResumed.emit() if self.studentConnected(): self.student.sendMessage(TeachingMsg(TeachingMsg.SIM_RESUMED))
def tickOnce(self): if not self.frozen: self.tick_interval = now() - self.lastLiveUpdateTime() hdg_before_tick = self.params.heading alt_before_tick = self.params.altitude self.doTick() self.hdg_tick_diff = self.params.heading.diff(hdg_before_tick) self.alt_tick_diff = self.params.altitude.diff(alt_before_tick) self.updateLiveStatus(self.params.position, self.params.geometricAltitude(), self.xpdrData())
def __init__(self, sender, text, recipient=None, private=False): self.sent_by = sender self.known_recipient = recipient self.text = text self.private = private if recipient == None and private: self.private = False print( 'WARNING: Cannot make message private without an identified recipient; made public.' ) self.msg_time_stamp = now()
def __init__(self, parent, atc_pov, acft_callsign, atc_callsign, xfr=None): QAbstractTableModel.__init__(self, parent) self.atc_pov = atc_pov self.acft_callsign = acft_callsign self.data_authority = atc_callsign self.initiator = xfr # Transferring ATC, or None if initiated by ACFT self.messages = [] self.connect_time = now() self.disconnect_time = None self.transferred_to = None self.expecting = False # True if either party is expecting an answer self.timed_out = False # True if other party took too long to answer self.problems = {} # int msg index -> str problem to resolve
def flightIsInTimeWindow(self, half_width, ref=None, strict=False): dep = self.details[FPL.TIME_OF_DEP] if dep == None: return False if ref == None: ref = now() lo = ref - half_width hi = ref + half_width eta = some(self.ETA(), dep) if strict: return dep >= lo and eta <= hi else: return dep <= hi and eta >= lo
def addPhysicalRunway(self, width, surface, rwy1, rwy2): rwy1._opposite_runway = rwy2 rwy2._opposite_runway = rwy1 rwy1._orientation = rwy1.thr.headingTo(rwy2.thr) rwy2._orientation = rwy2.thr.headingTo(rwy1.thr) rwy1._physical_runway = rwy2._physical_runway = len( self.physical_runways) rwy = min(rwy1, rwy2, key=(lambda r: r.name)) self.physical_runways.append((rwy, rwy.opposite(), width, surface)) self.physical_RWY_box_WTC_timer.append( (now() - timedelta(days=1), None)) self.directional_runways[rwy1.name] = rwy1 self.directional_runways[rwy2.name] = rwy2
def __init__(self, gui): QObject.__init__(self) self.ticker = Ticker(self.scan, parent=gui) self.last_sweep = now() # to be updated with current time at each blip self.aircraft_list = [] # Aircraft list self.blips_invisible = { } # str -> int; number of blips for which ACFT callsign has been invisible self.soft_links = [] # (Strip, Aircraft) pairs self.known_EMG_squawkers = set() # str identifiers self.runway_occupation = {} # int -> list of ACFT identifiers if env.airport_data != None: for i in range(env.airport_data.physicalRunwayCount()): self.runway_occupation[i] = []
def terminate(self, xfr=None): if self.expecting: # should imply message count > 0 problem_row = self.msgCount() - 1 self.timed_out = False self.expecting = False self._markProblem(problem_row, 'Expected answer never received') self.dataChanged.emit(self.index(problem_row, 2), self.index(problem_row, 2)) if self.isLive(): self.disconnect_time = now() self.transferred_to = xfr self.statusChanged.emit() else: print('WARNING: CPDLC connection already terminated.')
def __init__(self, identifier, acft_type, init_position, init_geom_alt): self.identifier = identifier # assumed unique self.aircraft_type = acft_type # "REAL TIME" VALUES self.live_update_time = now() self.live_position = init_position, init_geom_alt # EarthCoords, geom AMSL self.live_XPDR_data = {} # sqkey -> value mappings available from live update # UPDATED DATA init_snapshot = RadarSnapshot(self.live_update_time, init_position, init_geom_alt) self.radar_snapshots = [init_snapshot] # snapshot history; list must not be empty self.conflict = Conflict.NO_CONFLICT # USER OPTIONS self.individual_cheat = False self.ignored = False # FLAGS self.spawned = True self.frozen = False
def updateTimeStr(self): ''' If METAR recent enough, returns a human-readable time string. Otherwise returns the 'Z'-suffixed METAR timestamp. ''' match = update_time_regexp.search(self.METAR_string) if match: day = int(match.group(1)) timestr_update = match.group(2) t = now() day_now = t.day timestr_now = '%02d%02d' % (t.hour, t.minute) if day == day_now and timestr_update <= timestr_now or day == day_now - 1 and timestr_update > timestr_now: return '%s:%s' % (timestr_update[:2], timestr_update[2:]) else: return '%s%sZ' % (match.group(1), timestr_update) return None
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setupUi(self) t = now() qdt = QDateTime(t.year, t.month, t.day, t.hour, t.minute, timeSpec=Qt.UTC) self.beginTime_edit.setDateTime(qdt) self.endTime_edit.setTime(QTime((t.hour + 2) % 24, 0)) self.frequency_edit.addFrequencies([ (frq, descr) for frq, descr, t in env.frequencies ]) self.frequency_edit.clearEditText() self.announce_button.clicked.connect(self.announceSession) self.cancel_button.clicked.connect(self.reject)
def __init__(self, from_me, msg_type, contents=None): self.from_me = from_me # True = sent by me to them; False otherwise self.msg_type = msg_type self.msg_contents = contents self.time_stamp = now()
def data(self, index, role): fpl = self.FPL_list[index.row()] col = index.column() if role == Qt.DisplayRole: if col == 0: if fpl.existsOnline() and fpl.needsUpload(): # not in sync with online version return '!!' elif col == 1: return some(fpl[FPL.CALLSIGN], '?') elif col == 2: return fpl.shortDescr_AD() elif col == 3: return fpl.shortDescr_time() elif role == Qt.DecorationRole: if col == 0: if fpl.existsOnline(): status = fpl.status() if status == FPL.FILED: dep = fpl[FPL.TIME_OF_DEP] if dep != None and now() > dep + FPL_outdated_delay: # outdated colour = settings.colour('FPL_filed_outdated') else: colour = settings.colour('FPL_filed') elif status == FPL.OPEN: eta = fpl.ETA() if eta == None: # warning colour = settings.colour('FPL_open_noETA') elif now() > eta: # overdue colour = settings.colour('FPL_open_overdue') else: colour = settings.colour('FPL_open') elif status == FPL.CLOSED: colour = settings.colour('FPL_closed') return coloured_square_icon(colour) elif role == Qt.ToolTipRole: if col == 0: if fpl.existsOnline(): status = fpl.status() if status == FPL.FILED: dep = fpl[FPL.TIME_OF_DEP] txt = 'Outdated' if dep != None and now() > dep + FPL_outdated_delay else 'Filed' elif status == FPL.OPEN: eta = fpl.ETA() if eta == None: # warning txt = 'Open, ETA unknown' else: txt = 'Open' minutes_overtime = int(round((now() - eta).total_seconds())) // 60 if minutes_overtime >= 1: txt += ', arrival overdue by %d h %02d min' % (minutes_overtime // 60, minutes_overtime % 60) elif status == FPL.CLOSED: txt = 'Closed' else: txt = 'Status N/A' if fpl.needsUpload(): txt += '\n(local changes)' return txt else: return 'Not online'
def physicalRunway_restartWtcTimer(self, phyrwy_index, wtc): self.physical_RWY_box_WTC_timer[phyrwy_index] = now(), wtc
def physicalRunwayWtcTimer(self, phyrwy_index): t, wtc = self.physical_RWY_box_WTC_timer[phyrwy_index] return now() - t, wtc
def pauseSession(self): if self.isRunning() and self.simulation_paused_at == None: self.simulation_paused_at = now() self.session_ticker.stop() signals.sessionPaused.emit()
def pauseSession(self): self.session_ticker.stop() self.simulation_paused_at = now() signals.sessionPaused.emit() if self.studentConnected(): self.student.sendMessage(TeachingMsg(TeachingMsg.SIM_PAUSED))
def addStrip(self, strip): self.beginInsertRows(QModelIndex(), 0, 0) self.discarded_strips.insert(0, (strip, now())) self.endInsertRows()
def scan(self): visible_aircraft = { a.identifier: a for a in settings.session_manager.getAircraft() if a.isRadarVisible() } ## UPDATE AIRCRAFT LIST lost_contacts = [] for got_acft in self.aircraft_list: try: ignore = visible_aircraft.pop(got_acft.identifier) got_acft.saveRadarSnapshot() self.blips_invisible[got_acft.identifier] = 0 except KeyError: count = self.blips_invisible[got_acft.identifier] if count < settings.invisible_blips_before_contact_lost: self.blips_invisible[got_acft.identifier] = count + 1 else: lost_contacts.append(got_acft.identifier) # Remove lost aircraft for acft in pop_all(self.aircraft_list, lambda acft: acft.identifier in lost_contacts): strip = env.linkedStrip(acft) del self.blips_invisible[acft.identifier] self.known_EMG_squawkers.discard(acft.identifier) self.lostContact.emit(acft) if strip != None: signals.controlledContactLost.emit(strip, acft.coords()) # Add newly visible aircraft for new_acft in visible_aircraft.values(): new_acft.saveRadarSnapshot() self.aircraft_list.append(new_acft) self.blips_invisible[new_acft.identifier] = 0 self.newContact.emit(new_acft) ## CHECK FOR NEW EMERGENCIY SQUAWKS for acft in self.aircraft_list: if acft.xpdrCode() in XPDR_emergency_codes: if acft.identifier not in self.known_EMG_squawkers: self.known_EMG_squawkers.add(acft.identifier) self.emergencySquawk.emit(acft) else: self.known_EMG_squawkers.discard(acft.identifier) ## CHECK FOR NEW/LOST RADAR IDENTIFICATIONS if settings.traffic_identification_assistant: found_S_links = [] found_A_links = [] for strip in env.strips.listStrips( lambda s: s.linkedAircraft() == None): mode_S_found = False # Try mode S identification if strip.lookup(FPL.CALLSIGN) != None: scs = strip.lookup(FPL.CALLSIGN).upper() if env.strips.count( lambda s: s.lookup(FPL.CALLSIGN) != None and s. lookup(FPL.CALLSIGN).upper() == scs) == 1: candidates = [ acft for acft in self.aircraft_list if acft.xpdrCallsign() != None and acft.xpdrCallsign().upper() == scs ] if len(candidates) == 1: found_S_links.append((strip, candidates[0])) mode_S_found = True # Try mode A identification if not mode_S_found: ssq = strip.lookup(assigned_SQ_detail) if ssq != None and env.strips.count(lambda s: \ s.lookup(assigned_SQ_detail) == ssq and s.linkedAircraft() == None) == 1: # only one non-linked strip with this SQ candidates = [acft for acft in self.aircraft_list if not any(a is acft for s, a in found_S_links) \ and acft.xpdrCode() == ssq and env.linkedStrip(acft) == None] if len(candidates) == 1: # only one aircraft matching found_A_links.append((strip, candidates[0])) for s, a in pop_all( self.soft_links, lambda sl: not any(sl[0] is s and sl[ 1] is a for s, a in found_S_links + found_A_links)): s.writeDetail(soft_link_detail, None) for s, a, m in [(s, a, True) for s, a in found_S_links ] + [(s, a, False) for s, a in found_A_links]: if not any(sl[0] is s and sl[1] is a for sl in self.soft_links): # new found soft link if strip.lookup( received_from_detail ) != None and settings.strip_autolink_on_ident and ( m or settings.strip_autolink_include_modeC): s.linkAircraft(a) else: # strip not automatically linked; notify of a new identification self.soft_links.append((s, a)) s.writeDetail(soft_link_detail, a) signals.aircraftIdentification.emit(s, a, m) ## UPDATE POSITION/ROUTE WARNINGS conflicts = { acft.identifier: Conflict.NO_CONFLICT for acft in self.aircraft_list } traffic_for_route_checks = [] for strip in env.strips.listStrips( ): # check for position conflicts and build list of traffic to check for routes later acft = strip.linkedAircraft() if acft != None and acft.identifier in conflicts: # controlled traffic with radar contact for other in self.aircraft_list: if other is not acft and position_conflict_test( acft, other ) == Conflict.NEAR_MISS: # positive separation loss detected conflicts[acft.identifier] = conflicts[ other.identifier] = Conflict.NEAR_MISS if not bypass_route_conflict_check(strip): traffic_for_route_checks.append(acft) if settings.route_conflict_warnings: # check for route conflicts while traffic_for_route_checks != []: # progressively emptying the list acft = traffic_for_route_checks.pop() for other in traffic_for_route_checks: c = path_conflict_test(acft, other) conflicts[acft.identifier] = max( conflicts[acft.identifier], c) conflicts[other.identifier] = max( conflicts[other.identifier], c) # now update aircraft conflicts and emit signals if any are new new_near_miss = new_path_conflict = False for contact in self.aircraft_list: new_conflict = conflicts[contact.identifier] if new_conflict > contact.conflict: new_near_miss |= new_conflict == Conflict.NEAR_MISS new_path_conflict |= new_conflict in [ Conflict.DEPENDS_ON_ALT, Conflict.PATH_CONFLICT ] contact.conflict = new_conflict if new_path_conflict: self.pathConflict.emit() if new_near_miss: self.nearMiss.emit() ## UPDATE RUNWAY OCCUPATION for phrwy in self.runway_occupation: new_occ = [] if settings.monitor_runway_occupation: rwy1, rwy2 = env.airport_data.physicalRunway(phrwy) width_metres = env.airport_data.physicalRunwayData(phrwy)[0] thr1 = rwy1.threshold().toRadarCoords() thr2 = rwy2.threshold().toRadarCoords() w = m2NM * width_metres for acft in self.aircraft_list: if acft.considerOnGround(): if acft.coords().toRadarCoords().isBetween( thr1, thr2, w / 2): # ACFT is on RWY new_occ.append(acft) if not any( a is acft for a in self.runway_occupation[phrwy] ): # just entered the RWY: check if alarm must sound try: boxed_link = env.strips.findStrip( lambda strip: strip.lookup( runway_box_detail) == phrwy ).linkedAircraft() except StopIteration: # no strip boxed on this runway if rwy1.inUse() or rwy2.inUse( ): # entering a non-reserved but active RWY self.runwayIncursion.emit(phrwy, acft) else: # RWY is reserved if boxed_link == None and env.linkedStrip( acft ) == None or boxed_link is acft: # entering ACFT is the one cleared to enter, or can be if self.runway_occupation[ phrwy] != []: # some ACFT was/were already on RWY call_guilty = acft if boxed_link == None else self.runway_occupation[ phrwy][0] self.runwayIncursion.emit( phrwy, call_guilty) else: # entering ACFT is known to be different from the one cleared to enter self.runwayIncursion.emit(phrwy, acft) self.runway_occupation[phrwy] = new_occ # Finished aircraft stuff self.last_sweep = now() self.blip.emit()
def filterAcceptsRow(self, sourceRow, sourceParent): msg = self.sourceModel().messageOnRow(sourceRow) return msg.sender() not in self.hidden_senders \ and (settings.text_chat_history_time == None or now() - msg.timeStamp() <= settings.text_chat_history_time)
def receiveMsgFromTeacher(self, msg): #DEBUG if msg.type != TeachingMsg.TRAFFIC:# #DEBUG print('=== STUDENT RECEIVES ===\n%s\n=== End ===' % msg.data) if msg.type == TeachingMsg.ACFT_KILLED: callsign = msg.strData() if env.cpdlc.isConnected(callsign): env.cpdlc.endDataLink(callsign) for acft in pop_all(self.traffic, lambda a: a.identifier == callsign): signals.aircraftKilled.emit(acft) elif msg.type == TeachingMsg.TRAFFIC: # traffic update; contains FGMS packet fgms_packet = msg.binData() update_FgmsAircraft_list(self.traffic, fgms_packet) send_packet_to_views(fgms_packet) self.teacher.sendMessage(TeachingMsg(TeachingMsg.TRAFFIC)) elif msg.type == TeachingMsg.SIM_PAUSED: self.teacher_paused_at = now() signals.sessionPaused.emit() elif msg.type == TeachingMsg.SIM_RESUMED: pause_delay = now() - self.teacher_paused_at for acft in self.traffic: acft.moveHistoryTimesForward(pause_delay) self.teacher_paused_at = None signals.sessionResumed.emit() elif msg.type == TeachingMsg.ATC_TEXT_CHAT: lines = msg.strData().split('\n') if len(lines) == 2: signals.incomingAtcTextMsg.emit( ChatMessage(lines[0], lines[1], recipient=student_callsign, private=True)) else: print( 'ERROR: Invalid format in received ATC text chat from teacher.' ) elif msg.type == TeachingMsg.STRIP_EXCHANGE: line_sep = msg.strData().split('\n', maxsplit=1) fromATC = line_sep[0] strip = Strip.fromEncodedDetails( '' if len(line_sep) < 2 else line_sep[1]) strip.writeDetail(received_from_detail, fromATC) signals.receiveStrip.emit(strip) elif msg.type == TeachingMsg.SX_LIST: to_remove = set(env.ATCs.knownATCs()) to_remove.discard(teacher_callsign) for line in msg.strData().split('\n'): if line != '': # last line is empty lst = line.rsplit('\t', maxsplit=1) try: frq = CommFrequency(lst[1]) if len(lst) == 2 else None except ValueError: frq = None env.ATCs.updateATC(lst[0], None, None, frq) to_remove.discard(lst[0]) for atc in to_remove: env.ATCs.removeATC(atc) env.ATCs.refreshViews() elif msg.type == TeachingMsg.WEATHER: metar = msg.strData() station = metar.split(' ', maxsplit=1)[0] if station == settings.primary_METAR_station and metar != self.known_METAR: self.known_METAR = metar signals.newWeather.emit(station, Weather(metar)) elif msg.type == TeachingMsg.PTT: # msg format: "b acft" where b is '1' or '0' for PTT on/off; acft is caller's identifier line_sep = msg.strData().split(' ', maxsplit=1) try: ptt = bool(int(line_sep[0])) caller = next(acft for acft in self.getAircraft() if acft.identifier == line_sep[1]) if ptt: env.rdf.receiveSignal(caller.identifier, lambda acft=caller: acft.coords()) else: env.rdf.dieSignal(caller.identifier) except StopIteration: print('Ignored PTT message from teacher (unknown ACFT %s).' % line_sep[1]) except (ValueError, IndexError): print('Error decoding PTT message value from teacher') elif msg.type == TeachingMsg.CPDLC: try: acft_callsign, line2 = msg.strData().split('\n', maxsplit=1) if line2 == '0': # ACFT is disconnecting env.cpdlc.endDataLink(acft_callsign) elif line2 == '1': # ACFT is connecting (CAUTION: teacher needs confirmation of accepted connection) if settings.controller_pilot_data_link: env.cpdlc.beginDataLink(acft_callsign, student_callsign) self.teacher.sendMessage( TeachingMsg( TeachingMsg.CPDLC, data=('%s\n%d' % (acft_callsign, settings.controller_pilot_data_link)))) elif line2.startswith(CPDLC_transfer_cmd_prefix ): # ACFT being transferred to me if settings.controller_pilot_data_link: # CAUTION: teacher needs confirmation of accepted connection xfr_auth = line2[len(CPDLC_transfer_cmd_prefix):] env.cpdlc.beginDataLink(acft_callsign, student_callsign, transferFrom=xfr_auth) self.teacher.sendMessage(TeachingMsg(TeachingMsg.CPDLC, \ data=('%s\n%s%s' % (acft_callsign, CPDLC_transfer_cmd_prefix, xfr_auth)))) else: self.teacher.sendMessage( TeachingMsg(TeachingMsg.CPDLC, data=('%s\n0' % acft_callsign))) elif line2.startswith( CPDLC_message_cmd_prefix): # ACFT sending a message encoded_msg = line2[len(CPDLC_message_cmd_prefix):] link = env.cpdlc.currentDataLink(acft_callsign) if link == None: print( 'Ignored CPDLC message sent from %s while not connected.' % acft_callsign) else: link.appendMessage( CpdlcMessage.fromText(False, encoded_msg)) else: print('Error decoding CPDLC command from teacher:', line2) except (IndexError, ValueError): print('Error decoding CPDLC message value from teacher') else: print('Unhandled message type from teacher: %s' % msg.type)
def updateLiveStatus(self, pos, geom_alt, xpdr_data): self.live_update_time = now() self.live_position = pos, geom_alt self.live_XPDR_data = xpdr_data