2014-08-24 22:03:08 -04:00
#!/usr/bin/env python
#
2016-11-23 08:50:56 -05:00
###############################################################################
# hb_router.py -- a call routing applicaiton for hblink.py
# Copyright (C) 2016 Cortney T. Buffington, N0MJS <n0mjs@me.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
###############################################################################
2014-08-24 22:03:08 -04:00
2015-08-12 11:06:30 -04:00
# This is a sample application that "plays" a voice tranmission from a file
# that was created with record.py. The file is just a pickle of an entire
# transmission.
#
# This program consults a list of "trigger groups" for each timeslot that
# will initiate playback. When playback occurs, several items are re-written:
# Source Subscriber: this DMRlink's local subscriber ID
# Source Peer: this DMRlink's local subscriber ID
# Timeslot: timeslot of the tranmission that triggered
# TGID: TGID of the message that triggered it
2014-08-24 22:03:08 -04:00
from __future__ import print_function
from twisted . internet import reactor
from binascii import b2a_hex as h
import sys , time
import cPickle as pickle
2014-12-20 10:14:54 -05:00
from dmrlink import IPSC , NETWORK , networks , logger , int_id , hex_str_3
2014-08-24 22:03:08 -04:00
2016-11-23 08:50:56 -05:00
__author__ = ' Cortney T. Buffington, N0MJS '
__copyright__ = ' Copyright (c) 2014 - 2015 Cortney T. Buffington, N0MJS and the K0USY Group '
__credits__ = ' Adam Fast, KC0YLK; Dave Kierzkowski KD8EYF '
__license__ = ' GNU GPLv3 '
__maintainer__ = ' Cort Buffington, N0MJS '
__email__ = ' n0mjs@me.com '
2014-08-24 22:03:08 -04:00
2015-08-11 22:18:36 -04:00
# Constants for this application
#
BURST_DATA_TYPE = {
' VOICE_HEAD ' : ' \x01 ' ,
' VOICE_TERM ' : ' \x02 ' ,
' SLOT1_VOICE ' : ' \x0A ' ,
' SLOT2_VOICE ' : ' \x8A '
}
# path+filename for the transmission to play back
filename = ' ../test.pickle '
2015-08-12 11:06:30 -04:00
# trigger logic - True, trigger on these IDs, False trigger on any but these IDs
2015-08-12 11:07:52 -04:00
trigger = True
2015-08-12 11:06:30 -04:00
2015-08-11 22:18:36 -04:00
# groups that we want to trigger playback of this file (ts1 and ts2)
2015-08-12 11:14:48 -04:00
# Note this is a python list type, even if there's just one value
2015-08-12 11:06:30 -04:00
trigger_groups_1 = [ ' \x00 \x00 \x01 ' , ' \x00 \x00 \x0D ' , ' \x00 \x00 \x64 ' ]
2015-08-12 11:48:32 -04:00
trigger_groups_2 = [ ' \x00 \x0C \x30 ' , ]
2014-08-24 22:03:08 -04:00
class playIPSC ( IPSC ) :
def __init__ ( self , * args , * * kwargs ) :
IPSC . __init__ ( self , * args , * * kwargs )
self . CALL_DATA = [ ]
2015-08-11 22:18:36 -04:00
self . event_id = 1
2014-08-24 22:03:08 -04:00
#************************************************
# CALLBACK FUNCTIONS FOR USER PACKET TYPES
#************************************************
#
2015-08-11 22:18:36 -04:00
def group_voice ( self , _network , _src_sub , _dst_group , _ts , _end , _peerid , _data ) :
2014-08-24 22:03:08 -04:00
if _end :
2015-08-12 11:57:02 -04:00
_self_peer = NETWORK [ _network ] [ ' LOCAL ' ] [ ' RADIO_ID ' ]
_self_src = _self_peer [ 1 : ]
2015-08-12 11:58:02 -04:00
if ( _peerid == _self_peer ) or ( _src_sub == _self_src ) :
2015-08-12 12:08:40 -04:00
logger . error ( ' ( %s ) Just received a packet that appears to have been originated by us. PeerID: %s Subscriber: %s TS: %s , TGID: %s ' , _network , int_id ( _peerid ) , int_id ( _src_sub ) , int ( _ts ) + 1 , int_id ( _dst_group ) )
2015-08-12 11:57:02 -04:00
return
2015-08-12 11:49:58 -04:00
if trigger == False :
2015-08-12 11:06:30 -04:00
if ( _ts == 0 and _dst_group not in trigger_groups_1 ) or ( _ts == 1 and _dst_group not in trigger_groups_2 ) :
return
else :
if ( _ts == 0 and _dst_group in trigger_groups_1 ) or ( _ts == 1 and _dst_group in trigger_groups_2 ) :
return
2015-08-13 22:27:56 -04:00
logger . info ( ' ( %s ) Event ID: %s - Playback triggered from SourceID: %s , TS: %s , TGID: %s , PeerID: %s ' , _network , self . event_id , int_id ( _src_sub ) , _ts + 1 , int_id ( _dst_group ) , int_id ( _peerid ) )
2015-08-12 11:06:30 -04:00
# Determine the type of voice packet this is (see top of file for possible types)
_burst_data_type = _data [ 30 ]
2015-08-12 10:21:20 -04:00
2015-08-12 11:06:30 -04:00
time . sleep ( 2 )
self . CALL_DATA = pickle . load ( open ( filename , ' rb ' ) )
2015-08-13 22:26:23 -04:00
logger . info ( ' ( %s ) Event ID: %s - Playing back file: %s ' , _network , self . event_id , filename )
2015-08-12 11:06:30 -04:00
for i in self . CALL_DATA :
_tmp_data = i
2015-08-12 10:21:20 -04:00
2015-08-12 11:06:30 -04:00
# re-Write the peer radio ID to that of this program
_tmp_data = _tmp_data . replace ( _peerid , _self_peer )
# re-Write the source subscriber ID to that of this program
_tmp_data = _tmp_data . replace ( _src_sub , _self_src )
# Re-Write the destination Group ID
_tmp_data = _tmp_data . replace ( _tmp_data [ 9 : 12 ] , _dst_group )
# Re-Write IPSC timeslot value
_call_info = int_id ( _tmp_data [ 17 : 18 ] )
if _ts == 0 :
_call_info & = ~ ( 1 << 5 )
elif _ts == 1 :
_call_info | = 1 << 5
_call_info = chr ( _call_info )
_tmp_data = _tmp_data [ : 17 ] + _call_info + _tmp_data [ 18 : ]
2015-08-12 10:26:32 -04:00
2015-08-12 11:06:30 -04:00
# Re-Write DMR timeslot value
# Determine if the slot is present, so we can translate if need be
if _burst_data_type == BURST_DATA_TYPE [ ' SLOT1_VOICE ' ] or _burst_data_type == BURST_DATA_TYPE [ ' SLOT2_VOICE ' ] :
# Re-Write timeslot if necessary...
2015-08-11 22:18:36 -04:00
if _ts == 0 :
2015-08-12 11:06:30 -04:00
_burst_data_type = BURST_DATA_TYPE [ ' SLOT1_VOICE ' ]
2015-08-11 22:18:36 -04:00
elif _ts == 1 :
2015-08-12 11:06:30 -04:00
_burst_data_type = BURST_DATA_TYPE [ ' SLOT2_VOICE ' ]
_tmp_data = _tmp_data [ : 30 ] + _burst_data_type + _tmp_data [ 31 : ]
2016-09-09 23:44:40 -04:00
2015-08-12 11:06:30 -04:00
# Send the packet to all peers in the target IPSC
self . send_to_ipsc ( _tmp_data )
time . sleep ( 0.06 )
self . CALL_DATA = [ ]
2015-08-13 22:26:23 -04:00
logger . info ( ' ( %s ) Event ID: %s - Playback Completed ' , _network , self . event_id )
2015-08-12 11:06:30 -04:00
self . event_id = self . event_id + 1
2014-08-24 22:03:08 -04:00
if __name__ == ' __main__ ' :
logger . info ( ' DMRlink \' record.py \' (c) 2014 N0MJS & the K0USY Group - SYSTEM STARTING... ' )
for ipsc_network in NETWORK :
if NETWORK [ ipsc_network ] [ ' LOCAL ' ] [ ' ENABLED ' ] :
networks [ ipsc_network ] = playIPSC ( ipsc_network )
2014-10-31 11:30:18 -04:00
reactor . listenUDP ( NETWORK [ ipsc_network ] [ ' LOCAL ' ] [ ' PORT ' ] , networks [ ipsc_network ] , interface = NETWORK [ ipsc_network ] [ ' LOCAL ' ] [ ' IP ' ] )
2014-08-24 22:03:08 -04:00
reactor . run ( )