예제 #1
0
 def createNewTraffic(self, spawn_coords, spawn_hdg):
     dialog = CreateTrafficDialog(spawn_coords, spawn_hdg, parent=self.gui)
     dialog.exec()
     if dialog.result() > 0:
         params = dialog.acftInitParams()
         params.XPDR_mode = new_traffic_XPDR_mode
         acft = ControlledAircraft(dialog.acftCallsign(), dialog.acftType(),
                                   params, None)
         acft.spawned = False
         acft.frozen = dialog.startFrozen()
         acft.tickOnce()
         self.aircraft_list.append(acft)
         if dialog.createStrip():
             strip = Strip()
             strip.writeDetail(FPL.CALLSIGN, acft.identifier)
             strip.writeDetail(FPL.ACFT_TYPE, acft.aircraft_type)
             strip.writeDetail(FPL.WTC, wake_turb_cat(acft.aircraft_type))
             strip.linkAircraft(acft)
             signals.receiveStrip.emit(strip)
         selection.selectAircraft(acft)
예제 #2
0
def strip_auto_print_check():
    if settings.session_manager.isRunning():
        for fpl in env.FPLs.findAll():
            reason_to_print = auto_print_strip_reason(fpl)
            if reason_to_print != None:
                strip = Strip()
                strip.linkFPL(fpl)
                strip.writeDetail(
                    rack_detail,
                    some(settings.auto_print_collecting_rack,
                         default_rack_name))
                strip.writeDetail(auto_printed_detail, True)
                fpl.strip_auto_printed = True
                env.strips.addStrip(strip)
                signals.stripAutoPrinted.emit(strip, reason_to_print)
                signals.selectionChanged.emit()
예제 #3
0
    def receiveMsgFromStudent(self, msg):
        #DEBUG if msg.type != TeachingMsg.TRAFFIC:
        #DEBUG 	print('=== TEACHERS RECEIVES ===\n%s\n=== End ===' % msg.data)
        if msg.type == TeachingMsg.ATC_TEXT_CHAT:
            lines = msg.strData().split('\n')
            if len(lines) == 2:
                signals.incomingAtcTextMsg.emit(
                    ChatMessage(student_callsign,
                                lines[1],
                                recipient=lines[0],
                                private=True))
            else:
                print(
                    'ERROR: Invalid format in received ATC text chat from student.'
                )
        elif msg.type == TeachingMsg.STRIP_EXCHANGE:
            line_sep = msg.strData().split('\n', maxsplit=1)
            toATC = line_sep[0]
            strip = Strip.fromEncodedDetails(
                '' if len(line_sep) < 2 else line_sep[1])
            strip.writeDetail(received_from_detail, student_callsign)
            if toATC != teacher_callsign:
                strip.writeDetail(sent_to_detail, toATC)
            signals.receiveStrip.emit(strip)
        elif msg.type == TeachingMsg.WEATHER:  # requesting weather information
            if msg.strData() == settings.primary_METAR_station:
                self.sendWeather()
        elif msg.type == TeachingMsg.TRAFFIC:  # acknowledging a traffic message
            if self.noACK_traffic_count > 0:
                self.noACK_traffic_count -= 1
            else:
                print('ERROR: Student acknowledging unsent traffic?!')

        elif msg.type == TeachingMsg.CPDLC:
            # Msg format in 2 lines, first being ACFT callsign, second is either of the following:
            #  - connect/disconnect: "0" or "1"
            #  - data authority transfer: CPDLC_transfer_cmd_prefix + ATC callsign transferring to/from
            #  - other: CPDLC_message_cmd_prefix + encoded message string
            try:
                acft_callsign, line2 = msg.strData().split('\n', maxsplit=1)
                if line2 == '0':  # ACFT disconnected by student
                    if env.cpdlc.isConnected(acft_callsign):
                        env.cpdlc.endDataLink(acft_callsign)
                    else:  # student is rejecting a connection (unable CPDLC)
                        QMessageBox.warning(
                            self.gui, 'CPDLC connection failed',
                            'Student is not accepting CPDLC connections.')
                elif line2 == '1':  # student confirming ACFT log-on
                    env.cpdlc.beginDataLink(acft_callsign, student_callsign)
                elif line2.startswith(
                        CPDLC_transfer_cmd_prefix
                ):  # student transferring or confirming transfer
                    atc = line2[len(CPDLC_transfer_cmd_prefix):]
                    if env.cpdlc.isConnected(
                            acft_callsign
                    ):  # student initiating transfer to next ATC
                        env.cpdlc.endDataLink(acft_callsign, transferTo=atc)
                    else:  # student confirming proposed transfer
                        env.cpdlc.beginDataLink(acft_callsign,
                                                student_callsign,
                                                transferFrom=atc)
                elif line2.startswith(CPDLC_message_cmd_prefix
                                      ):  # student ATC sent a message
                    encoded_msg = line2[len(CPDLC_message_cmd_prefix):]
                    link = env.cpdlc.currentDataLink(acft_callsign)
                    if link == None:
                        print(
                            'Ignored CPDLC message sent to %s while not connected.'
                            % acft_callsign)
                    else:
                        link.appendMessage(
                            CpdlcMessage.fromText(False, encoded_msg))
                else:
                    print('Error decoding CPDLC command from student:', line2)
            except (IndexError, ValueError):
                print('Error decoding CPDLC message value from student')
        else:
            print('ERROR: Unhandled message type from student: %s' % msg.type)
예제 #4
0
    def run(self):
        ## PREPARING QUERY
        pos = env.radarPos()
        qdict = {
            'username': settings.MP_social_name,
            'lon': pos.lon,
            'lat': pos.lat,
            'range': some(settings.ORSX_handover_range, settings.radar_range),
            'xmlVersion': '1.0',
            'contacts': ','.join(
                acft.identifier for acft in
                env.radar.contacts())  # should this be all FGMS connections?
        }
        if settings.publicised_frequency != None:
            qdict['frequency'] = str(settings.publicised_frequency)
        server_response = server_query('getFlightplans', qdict)
        ## USING RESPONSE
        if server_response != None:
            try:
                ww_root = ElementTree.fromstring(server_response)
            except ElementTree.ParseError as parse_error:
                print('Parse error in SX server data: %s' % parse_error)
                return
            new_ATCs = []

            # ATCs first
            for ww_atc in ww_root.find('atcsInRange').iter(
                    'atc'):  # NOTE the server sends the full list each time
                atc = ATC(ww_atc.find('callsign').text)
                atc.social_name = ww_atc.find('username').text
                atc.position = EarthCoords(float(ww_atc.find('lat').text),
                                           float(ww_atc.find('lon').text))
                ww_frq = ww_atc.find('frequency').text
                try:
                    atc.frequency = CommFrequency(ww_frq)
                except ValueError:
                    atc.frequency = None
                new_ATCs.append(atc)
            self.ATCs_on_last_run = new_ATCs

            # Then strip data (contact claims and handover)
            for ww_flightplan in ww_root.iter(
                    'flightplan'
            ):  # NOTE the server only sends those when something changes
                ww_header = ww_flightplan.find('header')
                ww_callsign = ww_header.find('callsign').text
                ww_owner = ww_header.find('owner').text
                if ww_owner == None:
                    if ww_callsign in self.current_contact_claims:
                        del self.current_contact_claims[ww_callsign]
                else:
                    self.current_contact_claims[ww_callsign] = ww_owner

                if ww_header.find(
                        'handover'
                ).text == settings.session_manager.myCallsign(
                ):  # RECEIVE A STRIP!
                    strip = Strip()
                    strip.writeDetail(received_from_detail, ww_owner)
                    strip.writeDetail(
                        assigned_SQ_detail,
                        ck_int(ww_header.find('squawk').text, base=8))
                    strip.writeDetail(assigned_altitude_detail,
                                      ww_header.find('assignedAlt').text)
                    # Ignored from WW header above: <flags>, <assignedRunway>, <assignedRoute>, <status>, <flight>
                    # Ignored from WW data below: <fuelTime>; used with ulterior motive: <pilot>
                    ww_data = ww_flightplan.find('data')
                    # ATC-pie hides a token in <pilot>, wake turb. on its left and callsign to its right
                    # e.g. <pilot>M__ATC-pie__X-FOO</pilot> for M turb. and X-FOO strip callsign
                    # If the token is absent, we know the strip is from OpenRadar
                    hidden_tokens = some(ww_data.find('pilot').text,
                                         '').split(ATCpie_hidden_string,
                                                   maxsplit=1)
                    if len(
                            hidden_tokens
                    ) == 1:  # hidden marker NOT present; previous strip editor was OpenRadar
                        strip.writeDetail(FPL.CALLSIGN, ww_callsign)
                    else:  # recognise strip edited with ATC-pie
                        strip.writeDetail(FPL.WTC, hidden_tokens[0])
                        strip.writeDetail(FPL.CALLSIGN, hidden_tokens[1])
                    strip.writeDetail(FPL.FLIGHT_RULES,
                                      ww_data.find('type').text)
                    strip.writeDetail(FPL.ACFT_TYPE,
                                      ww_data.find('aircraft').text)
                    strip.writeDetail(FPL.ICAO_DEP,
                                      ww_data.find('departure').text)
                    strip.writeDetail(FPL.ICAO_ARR,
                                      ww_data.find('destination').text)
                    strip.writeDetail(FPL.ROUTE, ww_data.find('route').text)
                    strip.writeDetail(FPL.CRUISE_ALT,
                                      ww_data.find('cruisingAlt').text)
                    spd = ck_int(ww_data.find('trueAirspeed').text)
                    if spd != None:
                        strip.writeDetail(FPL.TAS, Speed(spd))
                    strip.writeDetail(FPL.COMMENTS,
                                      ww_data.find('remarks').text)
                    # Possibly ignored details (OpenRadar confuses FPLs and strips): DEP time, EET, alt. AD, souls [*]
                    signals.receiveStrip.emit(strip)
                    send_update(ww_callsign, strip)  # Acknowledge strip
예제 #5
0
    def generateAircraftAndStrip(self):
        start_angle = uniform(0, 360)
        start_pos = env.radarPos().moved(Heading(start_angle, True),
                                         settings.solo_CTR_range_dist)
        end_pos = env.radarPos().moved(
            Heading(start_angle + 90 + uniform(1, 179), True),
            settings.solo_CTR_range_dist)
        transit_hdg = start_pos.headingTo(end_pos)
        dep_ad = world_navpoint_db.findClosest(env.radarPos().moved(transit_hdg.opposite(), \
          uniform(1.2 * settings.map_range, 5000)), types=[Navpoint.AD])
        dest_ad = world_navpoint_db.findClosest(env.radarPos().moved(transit_hdg, \
          uniform(1.2 * settings.map_range, 5000)), types=[Navpoint.AD])
        if env.pointOnMap(dep_ad.coordinates) or env.pointOnMap(
                dest_ad.coordinates):
            return None, None

        candidate_midpoints = [p for code in settings.solo_CTR_routing_points \
          for p in env.navpoints.findAll(code, types=[Navpoint.NDB, Navpoint.VOR, Navpoint.FIX]) \
          if start_pos.distanceTo(p.coordinates) < start_pos.distanceTo(end_pos)]
        midpoint = None if candidate_midpoints == [] else choice(
            candidate_midpoints)

        FLd10 = randint(settings.solo_CTR_floor_FL // 10,
                        settings.solo_CTR_ceiling_FL // 10)
        if settings.solo_CTR_semi_circular_rule == SemiCircRule.E_W and (FLd10 % 2 == 0) != (transit_hdg.magneticAngle() >= 180) \
         or settings.solo_CTR_semi_circular_rule == SemiCircRule.N_S and (FLd10 % 2 == 1) != (90 <= transit_hdg.magneticAngle() < 270):
            FLd10 += 1
            if 10 * FLd10 > settings.solo_CTR_ceiling_FL:
                return None, None
        p_alt = StdPressureAlt.fromFL(10 * FLd10)
        if not self.airbornePositionFullySeparated(start_pos, p_alt):
            return None, None
        acft_type = choice(self.playable_aircraft_types)
        hdg = start_pos.headingTo(some(midpoint, dest_ad).coordinates)
        params = SoloParams(Status(Status.AIRBORNE), start_pos, p_alt, hdg,
                            cruise_speed(acft_type))
        params.XPDR_code = env.nextSquawkCodeAssignment(XPDR_range_IFR_transit)
        new_acft = self.mkAiAcft(acft_type, params, dest_ad)
        dist_key = lambda atc: env.ATCs.getATC(atc).position.distanceTo(
            start_pos)
        received_from = min(env.ATCs.knownATCs(), key=dist_key)

        strip = Strip()
        strip.writeDetail(FPL.CALLSIGN, new_acft.identifier)
        strip.writeDetail(FPL.ACFT_TYPE, new_acft.aircraft_type)
        strip.writeDetail(FPL.WTC, wake_turb_cat(new_acft.aircraft_type))
        strip.writeDetail(FPL.FLIGHT_RULES, 'IFR')
        strip.writeDetail(FPL.ICAO_DEP, dep_ad.code)
        strip.writeDetail(FPL.ICAO_ARR, dest_ad.code)
        strip.writeDetail(FPL.CRUISE_ALT,
                          env.readStdAlt(new_acft.params.altitude))
        strip.writeDetail(assigned_altitude_detail,
                          strip.lookup(FPL.CRUISE_ALT))
        strip.writeDetail(assigned_SQ_detail, new_acft.params.XPDR_code)
        strip.writeDetail(received_from_detail, received_from)
        if midpoint != None:
            strip.insertRouteWaypoint(midpoint)

        new_acft.instructions.append(
            Instruction(Instruction.FOLLOW_ROUTE,
                        arg=strip.lookup(parsed_route_detail).dup()))
        return new_acft, strip
예제 #6
0
 def generateAircraftAndStrip(self):
     new_acft = received_from = None
     is_arrival = random() >= settings.solo_ARRvsDEP_balance
     if is_arrival:
         dep_ad = choose_dep_dest_AD(True)
         dest_ad = env.airport_data.navpoint
         midpoint = local_ee_point_closest_to(dest_ad,
                                              False)  # None if none found
         if settings.solo_role_APP:
             new_acft = self.new_arrival_APP(midpoint)
             received_from = 'CTR'
         elif settings.solo_role_TWR:
             new_acft = self.new_arrival_TWR()
             received_from = 'APP'
         elif settings.solo_role_GND:
             new_acft = self.new_arrival_GND()
             received_from = 'TWR'
     else:  # Create a departure
         dep_ad = env.airport_data.navpoint
         dest_ad = choose_dep_dest_AD(False)
         midpoint = local_ee_point_closest_to(dep_ad,
                                              True)  # None if none found
         if settings.solo_role_GND:
             new_acft = self.new_departure_GND(midpoint)
             received_from = 'DEL'
         elif settings.solo_role_TWR:
             new_acft = self.new_departure_TWR(midpoint)
             received_from = 'GND'
         elif settings.solo_role_DEP:
             new_acft = self.new_departure_DEP(midpoint)
             received_from = 'TWR'
     if new_acft == None:
         return None, None
     else:
         strip = Strip()
         strip.writeDetail(FPL.CALLSIGN, new_acft.identifier)
         strip.writeDetail(FPL.ACFT_TYPE, new_acft.aircraft_type)
         strip.writeDetail(FPL.WTC, wake_turb_cat(new_acft.aircraft_type))
         strip.writeDetail(FPL.FLIGHT_RULES, 'IFR')
         strip.writeDetail(assigned_SQ_detail, new_acft.params.XPDR_code)
         strip.writeDetail(received_from_detail, received_from)
         if received_from == 'CTR':
             strip.writeDetail(assigned_altitude_detail,
                               env.readStdAlt(new_acft.params.altitude))
         elif received_from == 'TWR' and not settings.solo_role_GND:
             strip.writeDetail(assigned_altitude_detail,
                               settings.solo_initial_climb_reading)
         # routing details
         strip.writeDetail(FPL.ICAO_DEP, dep_ad.code)
         strip.writeDetail(FPL.ICAO_ARR, dest_ad.code)
         if is_arrival and midpoint != None:  # arrival with local entry point
             try:
                 strip.writeDetail(
                     FPL.ROUTE,
                     world_routing_db.shortestRouteStr(dep_ad, midpoint) +
                     ' ' + midpoint.code)
             except ValueError:
                 strip.writeDetail(FPL.ROUTE, 'DCT %s' % midpoint.code)
         elif not is_arrival and midpoint != None:  # departure with local exit point
             try:
                 strip.writeDetail(
                     FPL.ROUTE, midpoint.code + ' ' +
                     world_routing_db.shortestRouteStr(midpoint, dest_ad))
             except ValueError:
                 strip.writeDetail(FPL.ROUTE, '%s DCT' % midpoint.code)
         return new_acft, strip
예제 #7
0
 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)
예제 #8
0
def new_strip_dialog(parent_widget, rack, linkToSelection=False):
    '''
	Returns the created strip if operation not aborted
	'''
    new_strip = Strip()
    new_strip.writeDetail(rack_detail, rack)
    if linkToSelection:
        new_strip.linkAircraft(selection.acft)
        if settings.strip_autofill_on_ACFT_link:
            new_strip.fillFromXPDR()
        new_strip.linkFPL(selection.fpl)
    dialog = StripDetailSheetDialog(parent_widget, new_strip)
    dialog.exec()
    if dialog.result() > 0:  # not rejected
        new_strip.writeDetail(rack_detail, dialog.selectedRack())
        env.strips.addStrip(new_strip)
        selection.selectStrip(new_strip)
        return new_strip
    else:
        return None