Example #1
0
def update_hblink_table(_config, _stats_table):
    # Is there a system in HBlink's config monitor doesn't know about?
    for _hbp in _config:
        if _config[_hbp]['MODE'] == 'MASTER':
            for _peer in _config[_hbp]['PEERS']:
                if int_id(_peer) not in _stats_table['MASTERS'][_hbp]['PEERS'] and _config[_hbp]['PEERS'][_peer]['CONNECTION'] == 'YES':
                    logger.info('Adding peer to CTABLE that has registerred: %s', int_id(_peer))
                    add_hb_peer(_config[_hbp]['PEERS'][_peer], _stats_table['MASTERS'][_hbp]['PEERS'], _peer)

    # Is there a system in monitor that's been removed from HBlink's config?
    for _hbp in _stats_table['MASTERS']:
        remove_list = []
        if _config[_hbp]['MODE'] == 'MASTER':
            for _peer in _stats_table['MASTERS'][_hbp]['PEERS']:
                if bytes_4(_peer) not in _config[_hbp]['PEERS']:
                    remove_list.append(_peer)

            for _peer in remove_list:
                logger.info('Deleting stats peer not in hblink config: %s', _peer)
                del (_stats_table['MASTERS'][_hbp]['PEERS'][_peer])

    # Update connection time
    for _hbp in _stats_table['MASTERS']:
        for _peer in _stats_table['MASTERS'][_hbp]['PEERS']:
            if bytes_4(_peer) in _config[_hbp]['PEERS']:
                _stats_table['MASTERS'][_hbp]['PEERS'][_peer]['CONNECTED'] = since(_config[_hbp]['PEERS'][bytes_4(_peer)]['CONNECTED'])

    for _hbp in _stats_table['PEERS']:
        if _stats_table['PEERS'][_hbp]['MODE'] == 'XLXPEER':
            if _config[_hbp]['XLXSTATS']['CONNECTION'] == "YES":
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTED'] = since(_config[_hbp]['XLXSTATS']['CONNECTED'])
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTION'] = _config[_hbp]['XLXSTATS']['CONNECTION']
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_SENT'] = _config[_hbp]['XLXSTATS']['PINGS_SENT']
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_ACKD'] = _config[_hbp]['XLXSTATS']['PINGS_ACKD']
            else:
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTED'] = "--   --"
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTION'] = _config[_hbp]['XLXSTATS']['CONNECTION']
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_SENT'] = 0
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_ACKD'] = 0
        else:
            if _config[_hbp]['STATS']['CONNECTION'] == "YES":
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTED'] = since(_config[_hbp]['STATS']['CONNECTED'])
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTION'] = _config[_hbp]['STATS']['CONNECTION']
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_SENT'] = _config[_hbp]['STATS']['PINGS_SENT']
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_ACKD'] = _config[_hbp]['STATS']['PINGS_ACKD']
            else:
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTED'] = "--   --"
                _stats_table['PEERS'][_hbp]['STATS']['CONNECTION'] = _config[_hbp]['STATS']['CONNECTION']
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_SENT'] = 0
                _stats_table['PEERS'][_hbp]['STATS']['PINGS_ACKD'] = 0
    
    cleanTE()
    build_stats()
Example #2
0
def pkt_gen(_rf_src, _dst_id, _peer, _slot, _phrase):

    # Calculate all of the static components up-front
    STREAM_ID = bytes_4(randint(0x00, 0xFFFFFFFF))
    SDP = _rf_src + _dst_id + _peer
    LC = LC_OPT + _dst_id + _rf_src

    HEAD_LC = bptc.encode_header_lc(LC)
    HEAD_LC = [HEAD_LC[:98], HEAD_LC[-98:]]

    TERM_LC = bptc.encode_terminator_lc(LC)
    TERM_LC = [TERM_LC[:98], TERM_LC[-98:]]

    EMB_LC = bptc.encode_emblc(LC)

    EMBED = []
    EMBED.append(BS_VOICE_SYNC)
    EMBED.append(EMB['BURST_B'][:8] + EMB_LC[1] + EMB['BURST_B'][-8:])
    EMBED.append(EMB['BURST_C'][:8] + EMB_LC[2] + EMB['BURST_C'][-8:])
    EMBED.append(EMB['BURST_D'][:8] + EMB_LC[3] + EMB['BURST_D'][-8:])
    EMBED.append(EMB['BURST_E'][:8] + EMB_LC[4] + EMB['BURST_E'][-8:])
    EMBED.append(EMB['BURST_F'][:8] + NULL_EMB_LC + EMB['BURST_F'][-8:])

    #initialize the HBP calls stream sequence to 0
    SEQ = 0

    # Send the Call Stream

    # Send 3 Voice Header Frames
    for i in range(3):
        pkt = b'DMRD' + bytes([SEQ]) + SDP + bytes(
            [_slot << 7 | HEADBITS]) + STREAM_ID + (
                HEAD_LC[0] + SLOT_TYPE['VOICE_LC_HEAD'][:10] + BS_DATA_SYNC +
                SLOT_TYPE['VOICE_LC_HEAD'][-10:] + HEAD_LC[1]).tobytes() + TAIL
        SEQ = (SEQ + 1) % 0x100
        yield pkt

    # Send each burst, six bursts per Superframe rotating through with the proper EMBED value per burst A-F
    for word in _phrase:
        for burst in range(0, len(word)):
            print(burst)
            pkt = b'DMRD' + bytes([SEQ]) + SDP + bytes([
                _slot << 7 | BURSTBITS[burst % 6]
            ]) + STREAM_ID + (word[burst + 0][0] + EMBED[burst % 6] +
                              word[burst + 0][1]).tobytes() + TAIL
            SEQ = (SEQ + 1) % 0x100
            yield pkt

    # Send a single Voice Terminator Frame
    pkt = b'DMRD' + bytes([SEQ]) + SDP + bytes(
        [_slot << 7 | TERMBITS]) + STREAM_ID + (
            TERM_LC[0] + SLOT_TYPE['VOICE_LC_TERM'][:10] + BS_DATA_SYNC +
            SLOT_TYPE['VOICE_LC_TERM'][-10:] + TERM_LC[1]).tobytes() + TAIL
    SEQ = (SEQ + 1) % 0x100
    yield pkt

    # Return False to indicate we're done.
    return False
Example #3
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
Example #4
0
    def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot,
                      _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
        if (_frame_type
                == HBPF_DATA_SYNC) and (_dtype_vseq == HBPF_SLT_VTERM) and (
                    _stream_id != self.last_stream):
            print(int_id(_stream_id), int_id(self.last_stream))
            self.last_stream = _stream_id
            print('start speech')
            speech = pkt_gen(bytes_3(3120101), bytes_3(2), bytes_4(3120119), 0,
                             [words['all_circuits'], words['all_circuits']])

            sleep(1)
            while True:
                try:
                    pkt = next(speech)
                except StopIteration:
                    break
                sleep(.058)
                self.send_system(pkt)
                print(bhex(pkt))
            print('end speech')
Example #5
0
    def master_datagramReceived(self, _data, _sockaddr):
        # Keep This Line Commented Unless HEAVILY Debugging!
        # logger.debug('(%s) RX packet from %s -- %s', self._system, _sockaddr, ahex(_data))

        # Extract the command, which is various length, all but one 4 significant characters -- RPTCL
        _command = _data[:4]

        if _command == DMRD:    # DMRData -- encapsulated DMR data frame
            _peer_id = _data[11:15]
            if _peer_id in self._peers \
                        and self._peers[_peer_id]['CONNECTION'] == 'YES' \
                        and self._peers[_peer_id]['SOCKADDR'] == _sockaddr:
                _seq = _data[4]
                _rf_src = _data[5:8]
                _dst_id = _data[8:11]
                _bits = _data[15]
                _slot = 2 if (_bits & 0x80) else 1
                #_call_type = 'unit' if (_bits & 0x40) else 'group'
                if _bits & 0x40:
                    _call_type = 'unit'
                elif (_bits & 0x23) == 0x23:
                    _call_type = 'vcsbk'
                else:
                    _call_type = 'group'
                _frame_type = (_bits & 0x30) >> 4
                _dtype_vseq = (_bits & 0xF) # data, 1=voice header, 2=voice terminator; voice, 0=burst A ... 5=burst F
                _stream_id = _data[16:20]
                #logger.debug('(%s) DMRD - Seqence: %s, RF Source: %s, Destination ID: %s', self._system, _seq, int_id(_rf_src), int_id(_dst_id))
                # ACL Processing
                if self._CONFIG['GLOBAL']['USE_ACL']:
                    if not acl_check(_rf_src, self._CONFIG['GLOBAL']['SUB_ACL']):
                        if self._laststrid[_slot] != _stream_id:
                            logger.info('(%s) CALL DROPPED WITH STREAM ID %s FROM SUBSCRIBER %s BY GLOBAL ACL', self._system, int_id(_stream_id), int_id(_rf_src))
                            self._laststrid[_slot] = _stream_id
                        return
                    if _slot == 1 and not acl_check(_dst_id, self._CONFIG['GLOBAL']['TG1_ACL']):
                        if self._laststrid[_slot] != _stream_id:
                            logger.info('(%s) CALL DROPPED WITH STREAM ID %s ON TGID %s BY GLOBAL TS1 ACL', self._system, int_id(_stream_id), int_id(_dst_id))
                            self._laststrid[_slot] = _stream_id
                        return
                    if _slot == 2 and not acl_check(_dst_id, self._CONFIG['GLOBAL']['TG2_ACL']):
                        if self._laststrid[_slot] != _stream_id:
                            logger.info('(%s) CALL DROPPED WITH STREAM ID %s ON TGID %s BY GLOBAL TS2 ACL', self._system, int_id(_stream_id), int_id(_dst_id))
                            self._laststrid[_slot] = _stream_id
                        return
                if self._config['USE_ACL']:
                    if not acl_check(_rf_src, self._config['SUB_ACL']):
                        if self._laststrid[_slot] != _stream_id:
                            logger.info('(%s) CALL DROPPED WITH STREAM ID %s FROM SUBSCRIBER %s BY SYSTEM ACL', self._system, int_id(_stream_id), int_id(_rf_src))
                            self._laststrid[_slot] = _stream_id
                        return
                    if _slot == 1 and not acl_check(_dst_id, self._config['TG1_ACL']):
                        if self._laststrid[_slot] != _stream_id:
                            logger.info('(%s) CALL DROPPED WITH STREAM ID %s ON TGID %s BY SYSTEM TS1 ACL', self._system, int_id(_stream_id), int_id(_dst_id))
                            self._laststrid[_slot] = _stream_id
                        return
                    if _slot == 2 and not acl_check(_dst_id, self._config['TG2_ACL']):
                        if self._laststrid[_slot]!= _stream_id:
                            logger.info('(%s) CALL DROPPED WITH STREAM ID %s ON TGID %s BY SYSTEM TS2 ACL', self._system, int_id(_stream_id), int_id(_dst_id))
                            self._laststrid[_slot] = _stream_id
                        return

                # The basic purpose of a master is to repeat to the peers
                if self._config['REPEAT'] == True:
                    pkt = [_data[:11], '', _data[15:]]
                    for _peer in self._peers:
                        if _peer != _peer_id:
                            pkt[1] = _peer
                            self.transport.write(b''.join(pkt), self._peers[_peer]['SOCKADDR'])
                            #logger.debug('(%s) Packet on TS%s from %s (%s) for destination ID %s repeated to peer: %s (%s) [Stream ID: %s]', self._system, _slot, self._peers[_peer_id]['CALLSIGN'], int_id(_peer_id), int_id(_dst_id), self._peers[_peer]['CALLSIGN'], int_id(_peer), int_id(_stream_id))


                # Userland actions -- typically this is the function you subclass for an application
                self.dmrd_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)

        elif _command == RPTL:    # RPTLogin -- a repeater wants to login
            _peer_id = _data[4:8]
            # Check to see if we've reached the maximum number of allowed peers
            if len(self._peers) < self._config['MAX_PEERS']:
                # Check for valid Radio ID
                if acl_check(_peer_id, self._CONFIG['GLOBAL']['REG_ACL']) and acl_check(_peer_id, self._config['REG_ACL']):
                    # Build the configuration data strcuture for the peer
                    self._peers.update({_peer_id: {
                        'CONNECTION': 'RPTL-RECEIVED',
                        'CONNECTED': time(),
                        'PINGS_RECEIVED': 0,
                        'LAST_PING': time(),
                        'SOCKADDR': _sockaddr,
                        'IP': _sockaddr[0],
                        'PORT': _sockaddr[1],
                        'SALT': randint(0,0xFFFFFFFF),
                        'RADIO_ID': str(int(ahex(_peer_id), 16)),
                        'CALLSIGN': '',
                        'RX_FREQ': '',
                        'TX_FREQ': '',
                        'TX_POWER': '',
                        'COLORCODE': '',
                        'LATITUDE': '',
                        'LONGITUDE': '',
                        'HEIGHT': '',
                        'LOCATION': '',
                        'DESCRIPTION': '',
                        'SLOTS': '',
                        'URL': '',
                        'SOFTWARE_ID': '',
                        'PACKAGE_ID': '',
                    }})
                    logger.info('(%s) Repeater Logging in with Radio ID: %s, %s:%s', self._system, int_id(_peer_id), _sockaddr[0], _sockaddr[1])
                    _salt_str = bytes_4(self._peers[_peer_id]['SALT'])
                    self.send_peer(_peer_id, b''.join([RPTACK, _salt_str]))
                    self._peers[_peer_id]['CONNECTION'] = 'CHALLENGE_SENT'
                    logger.info('(%s) Sent Challenge Response to %s for login: %s', self._system, int_id(_peer_id), self._peers[_peer_id]['SALT'])
                else:
                    self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
                    logger.warning('(%s) Invalid Login from %s Radio ID: %s Denied by Registation ACL', self._system, _sockaddr[0], int_id(_peer_id))
            else:
                self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
                logger.warning('(%s) Registration denied from Radio ID: %s Maximum number of peers exceeded', self._system, int_id(_peer_id))

        elif _command == RPTK:    # Repeater has answered our login challenge
            _peer_id = _data[4:8]
            if _peer_id in self._peers \
                        and self._peers[_peer_id]['CONNECTION'] == 'CHALLENGE_SENT' \
                        and self._peers[_peer_id]['SOCKADDR'] == _sockaddr:
                _this_peer = self._peers[_peer_id]
                _this_peer['LAST_PING'] = time()
                _sent_hash = _data[8:]
                _salt_str = bytes_4(_this_peer['SALT'])
                _calc_hash = bhex(sha256(_salt_str+self._config['PASSPHRASE']).hexdigest())
                if _sent_hash == _calc_hash:
                    _this_peer['CONNECTION'] = 'WAITING_CONFIG'
                    self.send_peer(_peer_id, b''.join([RPTACK, _peer_id]))
                    logger.info('(%s) Peer %s has completed the login exchange successfully', self._system, _this_peer['RADIO_ID'])
                else:
                    logger.info('(%s) Peer %s has FAILED the login exchange successfully', self._system, _this_peer['RADIO_ID'])
                    self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
                    del self._peers[_peer_id]
            else:
                self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
                logger.warning('(%s) Login challenge from Radio ID that has not logged in: %s', self._system, int_id(_peer_id))

        elif _command == RPTC:    # Repeater is sending it's configuraiton OR disconnecting
            if _data[:5] == RPTCL:    # Disconnect command
                _peer_id = _data[5:9]
                if _peer_id in self._peers \
                            and self._peers[_peer_id]['CONNECTION'] == 'YES' \
                            and self._peers[_peer_id]['SOCKADDR'] == _sockaddr:
                    logger.info('(%s) Peer is closing down: %s (%s)', self._system, self._peers[_peer_id]['CALLSIGN'], int_id(_peer_id))
                    self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
                    del self._peers[_peer_id]

            else:
                _peer_id = _data[4:8]      # Configure Command
                if _peer_id in self._peers \
                            and self._peers[_peer_id]['CONNECTION'] == 'WAITING_CONFIG' \
                            and self._peers[_peer_id]['SOCKADDR'] == _sockaddr:
                    _this_peer = self._peers[_peer_id]
                    _this_peer['CONNECTION'] = 'YES'
                    _this_peer['CONNECTED'] = time()
                    _this_peer['LAST_PING'] = time()
                    _this_peer['CALLSIGN'] = _data[8:16]
                    _this_peer['RX_FREQ'] = _data[16:25]
                    _this_peer['TX_FREQ'] =  _data[25:34]
                    _this_peer['TX_POWER'] = _data[34:36]
                    _this_peer['COLORCODE'] = _data[36:38]
                    _this_peer['LATITUDE'] = _data[38:46]
                    _this_peer['LONGITUDE'] = _data[46:55]
                    _this_peer['HEIGHT'] = _data[55:58]
                    _this_peer['LOCATION'] = _data[58:78]
                    _this_peer['DESCRIPTION'] = _data[78:97]
                    _this_peer['SLOTS'] = _data[97:98]
                    _this_peer['URL'] = _data[98:222]
                    _this_peer['SOFTWARE_ID'] = _data[222:262]
                    _this_peer['PACKAGE_ID'] = _data[262:302]

                    self.send_peer(_peer_id, b''.join([RPTACK, _peer_id]))
                    logger.info('(%s) Peer %s (%s) has sent repeater configuration', self._system, _this_peer['CALLSIGN'], _this_peer['RADIO_ID'])
                else:
                    self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
                    logger.warning('(%s) Peer info from Radio ID that has not logged in: %s', self._system, int_id(_peer_id))

        elif _command == RPTP:    # RPTPing -- peer is pinging us
                _peer_id = _data[7:11]
                if _peer_id in self._peers \
                            and self._peers[_peer_id]['CONNECTION'] == "YES" \
                            and self._peers[_peer_id]['SOCKADDR'] == _sockaddr:
                    self._peers[_peer_id]['PINGS_RECEIVED'] += 1
                    self._peers[_peer_id]['LAST_PING'] = time()
                    self.send_peer(_peer_id, b''.join([MSTPONG, _peer_id]))
                    logger.debug('(%s) Received and answered RPTPING from peer %s (%s)', self._system, self._peers[_peer_id]['CALLSIGN'], int_id(_peer_id))
                else:
                    self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
                    logger.warning('(%s) Ping from Radio ID that is not logged in: %s', self._system, int_id(_peer_id))

        elif _command == RPTO:
            _peer_id = _data[4:8]
            if _peer_id in self._peers \
                        and self._peers[_peer_id]['CONNECTION'] == 'YES' \
                        and self._peers[_peer_id]['SOCKADDR'] == _sockaddr:
                logger.info('(%s) Peer %s (%s) has send options: %s', self._system, self._peers[_peer_id]['CALLSIGN'], int_id(_peer_id), _data[8:])
                self.transport.write(b''.join([RPTACK, _peer_id]), _sockaddr)

        elif _command == DMRA:
            _peer_id = _data[4:8]
            logger.info('(%s) Recieved DMR Talker Alias from peer %s, subscriber %s', self._system, self._peers[_peer_id]['CALLSIGN'], int_id(_rf_src))

        else:
            logger.error('(%s) Unrecognized command. Raw HBP PDU: %s', self._system, ahex(_data))
Example #6
0
                _slot << 7 | BURSTBITS[burst % 6]
            ]) + STREAM_ID + (word[burst + 0][0] + EMBED[burst % 6] +
                              word[burst + 0][1]).tobytes() + TAIL
            SEQ = (SEQ + 1) % 0x100
            yield pkt

    # Send a single Voice Terminator Frame
    pkt = b'DMRD' + bytes([SEQ]) + SDP + bytes(
        [_slot << 7 | TERMBITS]) + STREAM_ID + (
            TERM_LC[0] + SLOT_TYPE['VOICE_LC_TERM'][:10] + BS_DATA_SYNC +
            SLOT_TYPE['VOICE_LC_TERM'][-10:] + TERM_LC[1]).tobytes() + TAIL
    SEQ = (SEQ + 1) % 0x100
    yield pkt

    # Return False to indicate we're done.
    return False


if __name__ == '__main__':
    from time import time

    speech = pkt_gen(bytes_3(3120101), bytes_3(3120), bytes_4(312000), 0,
                     [words['all_circuits'], words['all_circuits']])

    while True:
        try:
            pkt = next(speech)
        except StopIteration:
            break
        print(len(pkt), pkt[4], pkt)
Example #7
0
    for word in _phrase:
        for burst in range(0, len(word)):
            pkt = b'DMRD' + bytes([SEQ]) + SDP + bytes([_slot << 7 | BURSTBITS[burst % 6]]) + STREAM_ID + (word[burst + 0][0] + EMBED[burst % 6] + word[burst + 0][1]).tobytes() + TAIL
            SEQ = (SEQ + 1) % 0x100
            yield pkt

    # Send a single Voice Terminator Frame
    pkt = b'DMRD' + bytes([SEQ]) + SDP + bytes([_slot << 7 | TERMBITS]) + STREAM_ID + (TERM_LC[0] + SLOT_TYPE['VOICE_LC_TERM'][:10] + BS_DATA_SYNC + SLOT_TYPE['VOICE_LC_TERM'][-10:] + TERM_LC[1]).tobytes() + TAIL
    SEQ = (SEQ + 1) % 0x100
    yield pkt
    
    if SEQ == 255:
        SEQ = 0
    
    # Return False to indicate we're done.
    return False


if __name__ == '__main__':
    from time import time
    
    speech = pkt_gen(bytes_3(3120101), bytes_3(3120), bytes_4(312000), 0, [words['all_circuits'], words['all_circuits']])
    

    while True:
        try:
            pkt = next(speech)
        except StopIteration:
            break
        print(len(pkt), pkt[4], pkt)