Example #1
0
def send_instruction(callsign, instr, consider_cpdlc):
    '''
	Teacher sessions: direct control of selected aircraft with given instr (callsign match bypass).
	Other sessions:
	 - perform manager-dependant instruction to callsign
	 - give a cpdlcSuggGui to suggest sending through data link instead, if callsign is connected
	CAUTION: Instruction.encodeToStr raises NotImplementedError with non-encoded instruction types.
	'''
    if settings.session_manager.session_type == SessionType.TEACHER:
        if selection.acft == None:
            QMessageBox.critical(settings.session_manager.gui,
                                 'Traffic command error',
                                 'No aircraft selected.')
        elif settings.teacher_ACFT_requesting_CPDLC_vectors == selection.acft.identifier:
            instr_str = instr.encodeToStr()
            settings.session_manager.sendCpdlcMsg(
                selection.acft.identifier,
                CpdlcMessage(True, CpdlcMessage.REQUEST, contents=instr_str))
            QMessageBox.information(
                settings.session_manager.gui, 'CPDLC request sent',
                'Requested through data link: ' + instr_str)
        else:
            settings.session_manager.instructAircraftByCallsign(
                selection.acft.identifier, instr)
    elif consider_cpdlc and env.cpdlc.isConnected(callsign) and yesNo_question(settings.session_manager.gui, \
      'Send CPDLC instruction', instr.encodeToStr(), 'Send this instruction through data link to %s?' % callsign):
        settings.session_manager.sendCpdlcMsg(
            callsign,
            CpdlcMessage(True,
                         CpdlcMessage.INSTR,
                         contents=instr.encodeToStr()))
    else:
        settings.session_manager.instructAircraftByCallsign(callsign, instr)
Example #2
0
 def sendFreeTextMessage(self):
     msg = CpdlcMessage(True,
                        CpdlcMessage.FREE_TEXT,
                        contents=self.freeText_edit.text())
     self.freeText_edit.clear()
     settings.session_manager.sendCpdlcMsg(
         self.data_link_model.acftCallsign(), msg)
Example #3
0
 def rejectClicked(self):
     txt, ok = QInputDialog.getText(self, 'CPDLC reject message',
                                    'Reason/message (optional):')
     if ok:
         msg = CpdlcMessage(True, CpdlcMessage.REJECT, contents=txt)
         settings.session_manager.sendCpdlcMsg(
             self.data_link_model.acftCallsign(), msg)
 def sendCpdlcMsg(self, callsign, msg):
     link = env.cpdlc.currentDataLink(callsign)
     if link != None:
         link.appendMessage(msg)
         if msg.type(
         ) == CpdlcMessage.INSTR:  # other message types ignored (unimplemented in solo)
             try:
                 acft = next(
                     a for a in self.controlled_traffic if a.identifier ==
                     callsign)  # uncontrolled traffic is not in contact
                 acft.instruct([Instruction.fromEncodedStr(msg.contents())])
                 # FUTURE ingest before instruct to allow exception raised or (delayed?) WILCO msg before actually executing
             except StopIteration:  # ACFT not found or not connected
                 print('WARNING: Aircraft %s not found.' % callsign)
             except Instruction.Error as err:  # raised by ControlledAircraft.instruct
                 link.appendMessage(
                     CpdlcMessage(False,
                                  CpdlcMessage.REJECT,
                                  contents=str(err)))
             else:  # instruction sent and already accepted
                 link.appendMessage(CpdlcMessage(False, CpdlcMessage.ACK))
Example #5
0
 def ackButtonClicked(self):
     if self.data_link_model.msgCount() > 0:
         last_msg = self.data_link_model.lastMsg()
         if not last_msg.isFromMe() and last_msg.type(
         ) == CpdlcMessage.REQUEST:
             try:
                 instr = Instruction.fromEncodedStr(last_msg.contents())
             except ValueError:
                 QMessageBox.critical(
                     self, 'CPDLC comm error',
                     'Unable to decode request. Mismatching program versions?'
                 )
             else:
                 selection.writeStripAssignment(instr)
                 msg = CpdlcMessage(True,
                                    CpdlcMessage.INSTR,
                                    contents=instr.encodeToStr())
                 settings.session_manager.sendCpdlcMsg(
                     self.data_link_model.acftCallsign(), msg)
             return
     msg = CpdlcMessage(True, CpdlcMessage.ACK)
     settings.session_manager.sendCpdlcMsg(
         self.data_link_model.acftCallsign(), msg)
	def data(self, index, role):
		row = index.row()
		col = index.column()
		if role == Qt.DisplayRole:
			if row == 0: ## First row of a connection
				if col == 0:
					return rel_datetime_str(self.connectionTime(), seconds=True)
				elif col == 1 and self.initiator != None:
					return 'XFR'
				elif col == 2:
					if self.atc_pov:
						return 'ACFT log-on' if self.initiator == None else 'Received from %s' % self.initiator
					else: # ACFT point of view
						return 'Logged on' if self.initiator == None else '%s → %s' % (self.initiator, self.dataAuthority())
			elif row == self.rowCount() - 1 and not self.isLive(): ## Last row of a terminated or transferred connection
				if col == 0:
					return rel_datetime_str(self.disconnectionTime(), seconds=True)
				elif col == 1 and self.transferred_to != None:
					return 'XFR'
				elif col == 2:
					return 'Terminated' if self.transferred_to == None else 'Transferred to %s' % self.transferred_to
			else: ## Regular message row
				imsg = row - 1
				msg = self.messages[imsg]
				if col == 0:
					return rel_datetime_str(msg.timeStamp(), seconds=True)
				elif col == 1:
					prefix = '↓↑'[self.atc_pov] + '  ' if msg.isFromMe() else ''
					return prefix + CpdlcMessage.type2str(msg.type())
				elif col == 2:
					return msg.contents()
				elif col == 3:
					if imsg in self.problems:
						return self.problems[imsg]
					elif imsg == self.msgCount() - 1 and self.expecting:
						return self.statusStr()
Example #7
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)
Example #8
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)