Beispiel #1
0
    def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot,
                      _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
        pkt_time = time()
        dmrpkt = _data[20:53]
        _bits = _data[15]
        if _call_type == 'group':

            # Is this is a new call stream?
            if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']):
                self.STATUS['RX_START'] = pkt_time
                logger.info('(%s) *START RECORDING* STREAM ID: %s SUB: %s (%s) REPEATER: %s (%s) TGID %s (%s), TS %s', \
                                  self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot)
                self.CALL_DATA.append(_data)
                self.STATUS[_slot]['RX_STREAM_ID'] = _stream_id
                return

            # Final actions - Is this a voice terminator?
            if (_frame_type == const.HBPF_DATA_SYNC) and (
                    _dtype_vseq == const.HBPF_SLT_VTERM) and (
                        self.STATUS[_slot]['RX_TYPE'] !=
                        const.HBPF_SLT_VTERM) and (self.CALL_DATA):
                call_duration = pkt_time - self.STATUS['RX_START']
                self.CALL_DATA.append(_data)
                logger.info('(%s) *END   RECORDING* STREAM ID: %s',
                            self._system, int_id(_stream_id))
                sleep(2)
                logger.info('(%s) *START  PLAYBACK* STREAM ID: %s SUB: %s (%s) REPEATER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \
                                  self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration)
                if (int_id(_dst_id) == 9996):
                    fout = open(
                        '/home/mmdvm/' + str(int_id(_stream_id)) + '.ambe',
                        'w+b')
                for i in self.CALL_DATA:
                    if (int_id(_dst_id) == 9996):
                        fout.write(i)
#                   self.send_system(i)
                    self.send_system(i[:5] + bytes_3(int_id(_peer_id)) + i[8:])
                    #print(i)
                    sleep(0.06)
                if (int_id(_dst_id) == 9996):
                    fout.close()
                self.CALL_DATA = []
                logger.info('(%s) *END    PLAYBACK* STREAM ID: %s',
                            self._system, int_id(_stream_id))

            else:
                if self.CALL_DATA:
                    self.CALL_DATA.append(_data)

            # Mark status variables for use later
            self.STATUS[_slot]['RX_RFS'] = _rf_src
            self.STATUS[_slot]['RX_TYPE'] = _dtype_vseq
            self.STATUS[_slot]['RX_TGID'] = _dst_id
            self.STATUS[_slot]['RX_TIME'] = pkt_time
            self.STATUS[_slot]['RX_STREAM_ID'] = _stream_id
Beispiel #2
0
    def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot,
                      _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
        pkt_time = time()
        dmrpkt = _data[20:53]
        _bits = _data[15]

        if _call_type == 'group':

            # Is this is a new call stream?
            if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']):
                self.STATUS['RX_START'] = pkt_time
                logger.info('(%s) *START RECORDING* STREAM ID: %s SUB: %s (%s) REPEATER: %s (%s) TGID %s (%s), TS %s', \
                                  self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot)
                self.CALL_DATA.append(_data)
                self.STATUS[_slot]['RX_STREAM_ID'] = _stream_id
                return

            # Final actions - Is this a voice terminator?
            if (_frame_type == const.HBPF_DATA_SYNC) and (
                    _dtype_vseq == const.HBPF_SLT_VTERM) and (
                        self.STATUS[_slot]['RX_TYPE'] !=
                        const.HBPF_SLT_VTERM) and (self.CALL_DATA):
                call_duration = pkt_time - self.STATUS['RX_START']
                #Change the stream ID
                self.CALL_DATA.append(_data)
                logger.info('(%s) *END   RECORDING* STREAM ID: %s',
                            self._system, int_id(_stream_id))
                sleep(2)
                _new_stream_id = bytes_4(randint(0x00, 0xFFFFFFFF))
                logger.info('(%s) *START  PLAYBACK* STREAM ID: %s SUB: %s (%s) REPEATER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \
                                  self._system, int_id(_new_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration)

                for i in self.CALL_DATA:

                    i = i[:16] + _new_stream_id + i[20:]
                    self.send_system(i)
                    sleep(0.06)
                self.CALL_DATA = []
                logger.info('(%s) *END    PLAYBACK* STREAM ID: %s',
                            self._system, int_id(_new_stream_id))

            else:
                if self.CALL_DATA:
                    #Change the stream ID
                    self.CALL_DATA.append(_data)

            # Mark status variables for use later
            self.STATUS[_slot]['RX_RFS'] = _rf_src
            self.STATUS[_slot]['RX_TYPE'] = _dtype_vseq
            self.STATUS[_slot]['RX_TGID'] = _dst_id
            self.STATUS[_slot]['RX_TIME'] = pkt_time
            self.STATUS[_slot]['RX_STREAM_ID'] = _stream_id
Beispiel #3
0
def alias_call(_id, _dict):
    alias = get_alias(_id, _dict, 'CALLSIGN')
    if type(alias) == list:
        for x, item in enumerate(alias):
            if item == None:
                alias.pop(x)
        return ', '.join(alias)
    else:
        return str(alias)
Beispiel #4
0
def alias_string(_id, _dict):
    alias = get_alias(_id, _dict, 'CALLSIGN', 'CITY', 'STATE')
    if type(alias) == list:
        for x, item in enumerate(alias):
            if item == None:
                alias.pop(x)
        return ', '.join(alias)
    else:
        return alias
Beispiel #5
0
def alias_tgid(_id, _dict):
    alias = get_alias(_id, _dict, 'NAME')
    if type(alias) == list:
        return str(alias[0])
    else:
        return str(alias)
Beispiel #6
0
    def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot,
                      _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
        pkt_time = time()
        dmrpkt = _data[20:53]
        _bits = _data[15]

        if _call_type == 'group':

            # Is this is a new call stream?
            new_stream = (_stream_id != self.STATUS[_slot]['RX_STREAM_ID'])

            if new_stream:
                self.STATUS[_slot]['RX_START'] = pkt_time
                self.STATUS[_slot]['RX_LOSS'] = 0
                self.STATUS[_slot]['RX_SEQ'] = _seq
                logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \
                        self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot)
            else:
                # This could be much better, it will have errors during roll-over
                if _seq > (self.STATUS[_slot]['RX_SEQ'] + 1):
                    #print(_seq, self.STATUS[_slot]['RX_SEQ'])
                    self.STATUS[_slot]['RX_LOSS'] += _seq - (
                        self.STATUS[_slot]['RX_SEQ'] + 1)

            # Final actions - Is this a voice terminator?
            if (_frame_type == const.HBPF_DATA_SYNC) and (
                    _dtype_vseq == const.HBPF_SLT_VTERM) and (
                        self.STATUS[_slot]['RX_TYPE'] != const.HBPF_SLT_VTERM):
                call_duration = pkt_time - self.STATUS[_slot]['RX_START']
                logger.info('(%s) *CALL END*   STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Loss: %s, Duration: %s', \
                        self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, self.STATUS[_slot]['RX_LOSS'], call_duration)

            for _target in self._CONFIG['SYSTEMS']:
                if _target != self._system:

                    _target_status = systems[_target].STATUS
                    _target_system = self._CONFIG['SYSTEMS'][_target]

                    # BEGIN STANDARD CONTENTION HANDLING
                    #
                    # The rules for each of the 4 "ifs" below are listed here for readability. The Frame To Send is:
                    #   From a different group than last RX from this HBSystem, but it has been less than Group Hangtime
                    #   From a different group than last TX to this HBSystem, but it has been less than Group Hangtime
                    #   From the same group as the last RX from this HBSystem, but from a different subscriber, and it has been less than stream timeout
                    #   From the same group as the last TX to this HBSystem, but from a different subscriber, and it has been less than stream timeout
                    # The "continue" at the end of each means the next iteration of the for loop that tests for matching rules
                    #
                    if ((_dst_id != _target_status[_slot]['RX_TGID'])
                            and ((pkt_time - _target_status[_slot]['RX_TIME'])
                                 < _target_system['GROUP_HANGTIME'])):
                        if _frame_type == const.HBPF_DATA_SYNC and _dtype_vseq == const.HBPF_SLT_VHEAD and self.STATUS[
                                _slot]['RX_STREAM_ID'] != _stream_id:
                            logger.info(
                                '(%s) Call not routed to TGID %s, target active or in group hangtime: HBSystem: %s, TS: %s, TGID: %s',
                                self._system, int_id(_dst_id), _target, _slot,
                                int_id(_target_status[_slot]['RX_TGID']))
                        continue
                    if ((_dst_id != _target_status[_slot]['TX_TGID'])
                            and ((pkt_time - _target_status[_slot]['TX_TIME'])
                                 < _target_system['GROUP_HANGTIME'])):
                        if _frame_type == const.HBPF_DATA_SYNC and _dtype_vseq == const.HBPF_SLT_VHEAD and self.STATUS[
                                _slot]['RX_STREAM_ID'] != _stream_id:
                            logger.info(
                                '(%s) Call not routed to TGID%s, target in group hangtime: HBSystem: %s, TS: %s, TGID: %s',
                                self._system, int_id(_dst_id), _target, _slot,
                                int_id(_target_status[_slot]['TX_TGID']))
                        continue
                    if (_dst_id == _target_status[_slot]['RX_TGID']) and (
                        (pkt_time - _target_status[_slot]['RX_TIME']) <
                            const.STREAM_TO):
                        if _frame_type == const.HBPF_DATA_SYNC and _dtype_vseq == const.HBPF_SLT_VHEAD and self.STATUS[
                                _slot]['RX_STREAM_ID'] != _stream_id:
                            logger.info(
                                '(%s) Call not routed to TGID%s, matching call already active on target: HBSystem: %s, TS: %s, TGID: %s',
                                self._system, int_id(_dst_id), _target, _slot,
                                int_id(_target_status[_slot]['RX_TGID']))
                        continue
                    if (_dst_id == _target_status[_slot]['TX_TGID']) and (
                            _rf_src != _target_status[_slot]['TX_RFS']) and (
                                (pkt_time - _target_status[_slot]['TX_TIME']) <
                                const.STREAM_TO):
                        if _frame_type == const.HBPF_DATA_SYNC and _dtype_vseq == const.HBPF_SLT_VHEAD and self.STATUS[
                                _slot]['RX_STREAM_ID'] != _stream_id:
                            logger.info(
                                '(%s) Call not routed for subscriber %s, call route in progress on target: HBSystem: %s, TS: %s, TGID: %s, SUB: %s',
                                self._system, int_id(_rf_src), _target, _slot,
                                int_id(_target_status[_slot]['TX_TGID']),
                                int_id(_target_status[_slot]['TX_RFS']))
                        continue

                    # ACL Processing
                    if self._CONFIG['GLOBAL']['USE_ACL']:
                        if not acl_check(_rf_src,
                                         self._CONFIG['GLOBAL']['SUB_ACL']):
                            if _stream_id != _target_status[_slot][
                                    'TX_STREAM_ID']:
                                logger.info(
                                    '(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s FROM SUBSCRIBER %s BY GLOBAL ACL',
                                    _target, int_id(_stream_id),
                                    int_id(_rf_src))
                                _target_status[_slot][
                                    'TX_STREAM_ID'] = _stream_id
                            continue
                        if _slot == 1 and not acl_check(
                                _dst_id, self._CONFIG['GLOBAL']['TG1_ACL']):
                            if _stream_id != _target_status[_slot][
                                    'TX_STREAM_ID']:
                                logger.info(
                                    '(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY GLOBAL TS1 ACL',
                                    _target, int_id(_stream_id),
                                    int_id(_dst_id))
                                _target_status[_slot][
                                    'TX_STREAM_ID'] = _stream_id
                            continue
                        if _slot == 2 and not acl_check(
                                _dst_id, self._CONFIG['GLOBAL']['TG2_ACL']):
                            if _stream_id != _target_status[_slot][
                                    'TX_STREAM_ID']:
                                logger.info(
                                    '(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY GLOBAL TS2 ACL',
                                    _target, int_id(_stream_id),
                                    int_id(_dst_id))
                                _target_status[_slot][
                                    'TX_STREAM_ID'] = _stream_id
                            continue
                    if _target_system['USE_ACL']:
                        if not acl_check(_rf_src, _target_system['SUB_ACL']):
                            if _stream_id != _target_status[_slot][
                                    'TX_STREAM_ID']:
                                logger.info(
                                    '(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s FROM SUBSCRIBER %s BY SYSTEM ACL',
                                    _target, int_id(_stream_id),
                                    int_id(_rf_src))
                                _target_status[_slot][
                                    'TX_STREAM_ID'] = _stream_id
                            continue
                        if _slot == 1 and not acl_check(
                                _dst_id, _target_system['TG1_ACL']):
                            if _stream_id != _target_status[_slot][
                                    'TX_STREAM_ID']:
                                logger.info(
                                    '(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY SYSTEM TS1 ACL',
                                    _target, int_id(_stream_id),
                                    int_id(_dst_id))
                                _target_status[_slot][
                                    'TX_STREAM_ID'] = _stream_id
                            continue
                        if _slot == 2 and not acl_check(
                                _dst_id, _target_system['TG2_ACL']):
                            if _stream_id != _target_status[_slot][
                                    'TX_STREAM_ID']:
                                logger.info(
                                    '(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY SYSTEM TS2 ACL',
                                    _target, int_id(_stream_id),
                                    int_id(_dst_id))
                                _target_status[_slot][
                                    'TX_STREAM_ID'] = _stream_id
                            continue

                    # Record this stuff for later
                    # Is this a new call stream?
                    if new_stream:
                        # Record the DST TGID and Stream ID
                        _target_status[_slot]['TX_START'] = pkt_time
                        _target_status[_slot]['TX_TGID'] = _dst_id
                        _target_status[_slot]['TX_RFS'] = _rf_src
                        _target_status[_slot]['TX_PEER'] = _peer_id
                        _target_status[_slot]['TX_STREAM_ID'] = _stream_id

                    _target_status[_slot]['TX_TIME'] = pkt_time

                    systems[_target].send_system(_data)
                    #logger.debug('(%s) Packet routed to system: %s', self._system, _target)

            # Mark status variables for use later
            self.STATUS[_slot]['RX_RFS'] = _rf_src
            self.STATUS[_slot]['RX_SEQ'] = _seq
            self.STATUS[_slot]['RX_TYPE'] = _dtype_vseq
            self.STATUS[_slot]['RX_TGID'] = _dst_id
            self.STATUS[_slot]['RX_TIME'] = pkt_time
            self.STATUS[_slot]['RX_STREAM_ID'] = _stream_id
Beispiel #7
0
    def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot,
                      _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
        # Capture data headers
        global n_packet_assembly
        #logger.info(_dtype_vseq)
        if int_id(_dst_id) == data_id:
            #logger.info(type(_seq))
            if type(_seq) is bytes:
                pckt_seq = int.from_bytes(_seq, 'big')
            else:
                pckt_seq = _seq
            if _call_type == call_type or (
                    _call_type == 'vcsbk'
                    and pckt_seq > 3):  #int.from_bytes(_seq, 'big') > 3 ):
                if _dtype_vseq == 6 or _dtype_vseq == 'group':
                    global btf
                    logger.info('Header from ' + str(int_id(_rf_src)))
                    logger.info(ahex(bptc_decode(_data)))
                    logger.info('Blocks to follow: ' +
                                str(ba2num(bptc_decode(_data)[65:72])))
                    btf = ba2num(bptc_decode(_data)[65:72])
                # Data blocks at 1/2 rate, see https://github.com/g4klx/MMDVM/blob/master/DMRDefines.h for data types. _dtype_seq defined here also
                if _dtype_vseq == 7:
                    btf = btf - 1
                    logger.info('Block #: ' + str(btf))
                    #logger.info(_seq)
                    global packet_assembly
                    logger.info('Data block from ' + str(int_id(_rf_src)))
                    logger.info(ahex(bptc_decode(_data)))
                    if _seq == 0:
                        n_packet_assembly = 0
                        packet_assembly = ''

                    if btf < btf + 1:
                        n_packet_assembly = n_packet_assembly + 1
                        packet_assembly = packet_assembly + str(
                            bptc_decode(_data)
                        )  #str((decode_full_lc(b_packet)).strip('bitarray('))
                    # Use block 0 as trigger. $GPRMC must also be in string to indicate NMEA.
                    # This triggers the APRS upload
                    if btf == 0:  #_seq == 12:
                        final_packet = bitarray(
                            re.sub("\)|\(|bitarray|'", '',
                                   packet_assembly)).tobytes().decode(
                                       'utf-8', 'ignore')
                        if '$GPRMC' in final_packet:
                            logger.info(final_packet + '\n')
                            logger.info('Latitude: ' +
                                        re.sub(',', '', final_packet[29:40]) +
                                        ' Longitude: ' +
                                        re.sub(',', '', final_packet[41:53]) +
                                        ' Direction: ' +
                                        re.sub(',', '', final_packet[58:62]) +
                                        ' Speed: ' +
                                        re.sub(',', '', final_packet[53:58]))
                            # Begin APRS format and upload
                            aprs_loc_packet = str(
                                get_alias(int_id(_rf_src), subscriber_ids)
                            ) + '-' + str(user_ssid) + '>APRS,TCPIP*:/' + str(
                                datetime.datetime.utcnow().strftime("%H%M%Sh")
                            ) + str(final_packet[29:36]) + str(
                                final_packet[39]) + '/' + str(
                                    re.sub(',', '', final_packet[41:49])
                                ) + str(
                                    final_packet[52]
                                ) + '[/' + aprs_comment + ' DMR ID: ' + str(
                                    int_id(_rf_src))
                            logger.info(aprs_loc_packet)
                            try:
                                # Try parse of APRS packet. If it fails, it will not upload to APRS-IS
                                aprslib.parse(aprs_loc_packet)
                                AIS = aprslib.IS(aprs_callsign,
                                                 passwd=aprs_passcode,
                                                 host=aprs_server,
                                                 port=aprs_port)
                                AIS.connect()
                                AIS.sendall(aprs_loc_packet)
                                AIS.close()
                            except:
                                logger.info(
                                    'Failed to parse packet. Packet may be deformed. Not uploaded.'
                                )
                            # Get callsign based on DMR ID
                            #logger.info(get_alias(int_id(_rf_src), subscriber_ids))
                            # End APRS-IS upload
                        else:
                            logger.info(final_packet)
                        packet_assembly = ''
                    logger.info(_seq)
                    #logger.info(_dtype_vseq)
                logger.info(ahex(bptc_decode(_data)).decode('utf-8', 'ignore'))
                #logger.info(bitarray(re.sub("\)|\(|bitarray|'", '', str(bptc_decode(_data)).tobytes().decode('utf-8', 'ignore'))))

        else:
            pass