#!/usr/bin/env python # # Copyright 2005,2006,2007,2009 Free Software Foundation, Inc. # # Copyright 2009 Virginia Polytechnic Institute and State University # # GNU Radio 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, or (at your option) # any later version. # # GNU Radio 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 GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. # from gnuradio import gr, gru, modulation_utils from gnuradio import eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser from numpy import random import random, time, struct, sys, math from datetime import datetime # from current dir #from transmit_path import transmit_path #from receive_path import receive_path import usrp_transmit_path import usrp_receive_path try: from cross import * cross_import = True except ImportError: cross_import = False global sync_status,mode,ch,data_packet_delivery_count,n_rcvd, n_right sync_status = False #Defining modes of operation # sync: the two nodes are trying to rendezvous on a common channel # traffic: the two node are communicating information to each other mode = "sync" #Default mode is sync data_packet_delivery_count = 0 class my_top_block(gr.top_block): def __init__(self, mod_class, demod_class, rx_callback, options_tx,options_rx): gr.top_block.__init__(self) self.rxpath = usrp_receive_path.usrp_receive_path(demod_class, rx_callback, options_rx) self.txpath = usrp_transmit_path.usrp_transmit_path(mod_class, options_tx) self.connect(self.txpath); self.connect(self.rxpath); def main(): global stats_array, count_array, time_array, n_rcvd global n_right, sync_status, mode, ch, data_packet_delivery_count global n_attempts, return_flag, crossShellHost, crossShellPort data_packet_delivery_count_previous = 0 n_rcvd = 0 n_right = 0 n_attempts = 5 return_flag = 0 count_array = [ 0, 0, 0, 0, 0] time_array = [ 0, 0, 0, 0, 0] stats_array = [ 0, 0, 0, 0, 0,0,0,0,0,0,0,0,0,0,0] def send_pkt(self, payload='', eof=False): return self.txpath.send_pkt(payload, eof) def get_real_channel(channel): real_channel = 1; get_channel = { 1: 1, 2: 7, 3: 8, 4: 14 } real_channel = get_channel[channel] return real_channel def get_average_time(channel,absent_time): global count_array, time_array count_array[channel] = count_array[channel] + 1 average_time = (time_array[channel] + absent_time) / count_array[channel] return average_time def get_freq(hop_freq,probe_level,absent_time,cross): # Convert hop_freq to our unique channel list if cross == True: freq_channel = { 462562500: 1, 462712500: 2, 467562500: 3, 467712500: 4, } currentParameters = Parameter(1) currentParameters[0].name = "channel" currentParameters[0].value = freq_channel[hop_freq] o = Observable(2) o[0].value = probe_level o[0].name = "energy" o[1].value = absent_time o[1].name = "communication_time" # If time == 0 then we are scanning and we dont want to # use this time in the averaging process. if absent_time != 0: try: UpdateParameterPerformance(currentParameters,1,o,1) except: print "fail" else: # Get the average communication time average_time = get_average_time(freq_channel[hop_freq], absent_time) o[1].value = average_time o[1].name = "communication_time" try: UpdateParameterPerformance(currentParameters,1,o,2) except: print "fail" p = Parameter(1) p = GetOptimalParameters(o,2,currentParameters,1); channel = get_real_channel(int(p[0].value)) else: channel = int(random.choice([1,7,8,14])) if channel < 8: hop_freq = float(1e6 * (462.5625+(channel-1)*0.025))#setting the centre freq frequency for sending packets else: hop_freq = float(1e6 * (467.5625+(channel-8)*0.025))#setting the centre freq frequency for sending packets stats_array[channel] = stats_array[channel] + 1 print "\n1: ", stats_array[1], " 7: ",stats_array[7], " 8: ",stats_array[8], " 14: ", stats_array[14] return channel,hop_freq #returning the channel number and hop frequency def rx_callback(ok, payload): global n_rcvd, n_right,sync_status,mode,ch,data_packet_delivery_count ########################## sync #################################### if mode == "sync": if ok: (pktno,) = struct.unpack('!H', payload[0:2]) (sync_signal,) = struct.unpack('!s', payload[2]) (data_channel,) = struct.unpack('!H', payload[3:5]) if str(sync_signal) == 'o' and str(data_channel) == str(ch): sync_status = True #tb.stop() if str(sync_signal) == 's' and str(data_channel) == str(ch): sync_status = True data = 'o' pktno=0 ack_payload = struct.pack('!HsH', pktno & 0xffff,data,ch & 0xffff) #+ data send_pkt(tb,ack_payload) #sending back the acknowledgement ################################################################### ######################### traffic ################################# if mode == "traffic": if ok: (data_header,) = struct.unpack('!s', payload[0]) if data_header == 'd': data_packet_delivery_count = data_packet_delivery_count +1 comm = struct.unpack('!14s', payload[1:15]) data = 'dI am fine.....' #Sending this message payload = struct.pack('!15s', data) send_pkt(tb,payload) ############################################################## n_rcvd += 1 if ok: n_right += 1 mods = modulation_utils.type_1_mods() demods = modulation_utils.type_1_demods() # Set default values for the CROSS shell location. These can be overridden # via command-line parameters crossShellHost = "localhost" crossShellPort = "40000" #setting up the tx options parser parser_tx = OptionParser(option_class=eng_option, conflict_handler="resolve") parser_tx.add_option("-m", "--modulation", type="choice", choices=mods.keys(), default='gmsk',help="Select modulation from: %s [default=%%default]" % (', '.join(mods.keys()),)) parser_tx.add_option("-s", "--size", type="eng_float", default=1500, help="set packet size [default=%default]") parser_tx.add_option("-M", "--megabytes", type="eng_float", default=1.0, help="set megabytes to transmit [default=%default]") parser_tx.add_option("","--discontinuous", action="store_true", default=False, help="enable discontinous transmission (bursts of 5 packets)") parser_tx.add_option("","--from-file", default=None, help="use file for packet contents") parser_tx.add_option("-n", "--hostname", action="store", type="string", dest="crossShellHost", default="localhost", help="Set the hostname/IP for the VTCROSS shell"); parser_tx.add_option("-p", "--port", action="store", type="string", dest="crossShellPort", default="40000", help="Set the port for the VTCROSS shell"); expert_grp_tx = parser_tx.add_option_group("Expert_tx") dsa_grp = parser_tx.add_option_group("DSA Options") dsa_grp.add_option("-c", "--cross", action="store_true", default=False, help="Use the CROSS CBR Cognitive Engine for DSA channel decisions [default=off (random selection)].") dsa_grp.add_option("-T", "--threshold", type="eng_float", default=1.5e8, help="set primary user sensing energy threshold [default=%default]") usrp_transmit_path.add_options(parser_tx, expert_grp_tx) parser_tx.remove_option('-f'); parser_tx.remove_option('--tx-freq'); for mod in mods.values(): mod.add_options(expert_grp_tx) (options_tx, args_tx) = parser_tx.parse_args () if len(args_tx) != 0: parser_tx.print_help() sys.exit(1) ############# Setting some default values for tx side of the block options_tx.tx_freq = 462.5625e6 options_tx.samples_per_symbol = 2 options_tx.modulation = 'dbpsk' options_tx.fusb_block_size = 4096 options_tx.fusb_nblocks = 16 options_tx.bitrate = 0.0125e6 ############# if options_tx.tx_freq is None: sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") parser_tx.print_help(sys.stderr) sys.exit(1) parser_rx = OptionParser (option_class=eng_option, conflict_handler="resolve") expert_grp_rx = parser_rx.add_option_group("Expert_rx") usrp_receive_path.add_options(parser_rx, expert_grp_rx) parser_rx.remove_option('-f'); parser_rx.add_option("-c", "--cross", action="store_true", default=False, help="Use the CROSS engine for DSA decisions: default is random.") parser_rx.add_option("-T", "--threshold", type="eng_float", default=1.5e8, help="set primary user sensing energy threshold [default=%default]") parser_rx.add_option("-n", "--hostname", action="store", type="string", dest="crossShellHost", default="localhost", help="Set the hostname/IP for the VTCROSS shell"); parser_rx.add_option("-p", "--port", action="store", type="string", dest="crossShellPort", default="40000", help="Set the port for the VTCROSS shell"); (options_rx, args_rx) = parser_rx.parse_args () ############# Setting some default values for rx side of the block options_rx.rx_freq = 462.5625e6 #setting default rx_freq value options_rx.samples_per_symbol = 2 options_rx.modulation = 'dbpsk' options_rx.fusb_block_size = 4096 options_rx.fusb_nblocks = 16 options_rx.bitrate = 0.0125e6 ############# if options_rx.cross == True: if cross_import == False: print "\n\n[[ CROSS Import failed.. Defaulting to RANDOM channel selection ]]" print "[[ Using the RANDOM channel selection algorithm ]]\n\n" options_rx.cross = False else: print "[[ Using the CROSS DSA Cognitive Engine ]]" crossShellHost = options_rx.crossShellHost crossShellPort = options_rx.crossShellPort print "[[ VTCROSS shell located at " + crossShellHost + ":" + crossShellPort + " ]]" SetCrossShellLocation(crossShellHost, crossShellPort) else: print "[[ Using the RANDOM channel selection algorithm ]]\n\n" # build the graph tb = my_top_block(mods[options_tx.modulation], demods[options_rx.modulation], rx_callback,options_tx, options_rx) r = gr.enable_realtime_scheduling() if r != gr.RT_OK: print "Warning: failed to enable realtime scheduling" tb.start() #listening to random frequencies untill a match is found running = True ch_energy = tb.rxpath.probe.level() #setting initial value hop_freq = options_tx.tx_freq # = options_rx.rx_freq...same for tx and rx side # Scan all channels first for inital data #time.sleep(0.1) print "\n[[ Scanning channels for network nodes ]]\n" while running: ################################################sync mode#################################### if mode == "sync": if sync_status != True: if return_flag == 0: ch,hop_freq = get_freq(hop_freq,ch_energy,0,options_rx.cross) else: ch,hop_freq = get_freq(hop_freq,ch_energy,elapsed_time,options_rx.cross) return_flag = 0 tb.txpath.u.set_center_freq(hop_freq) tb.rxpath.u.set_center_freq(hop_freq) ch_energy = tb.rxpath.probe.level() #check if primary user is present if int(ch_energy) > 1.5e8: #if primary user is there then dont transmit on this channel continue nbytes = 5 #int(1e6 * .0003) pkt_size = 5 n = 0 pktno = 0 while n < nbytes: if options_tx.from_file is None: data = 's' else: data = source_file.read(pkt_size - 2) if data == '': break; payload = struct.pack('!HsH', pktno & 0xffff,data,ch & 0xffff) #+ data send_pkt(tb,payload) n += len(payload) sys.stderr.write('.') if options_tx.discontinuous and pktno % 5 == 4: time.sleep(1) pktno += 1 time.sleep(0.1) else: print "\n\n[[ Network Node Found: Commencing communications on CHANNEL ", ch, " ]]\n"; n_attempts_counter = 0 mode = "traffic" data_packet_delivery_count = 0 sync_status="False" start_time = datetime.now() #measuring the time for which the primary user is away ################################################end of sync mode#################################### ################################################Communications mode################################# if mode == "traffic": nbytes = 15 pkt_size = 15 data_pktno = 0 n = 0 while n < nbytes: if options_tx.from_file is None: data = 'dHi how are you' #Sending this message else: data = source_file.read(pkt_size - 2) if data == '': break; payload = struct.pack('!15s', data) send_pkt(tb,payload) n += len(payload) sys.stderr.write('.') if options_tx.discontinuous and data_pktno % 5 == 4: time.sleep(1) data_pktno += 1 time.sleep(0.2 + 0.05*int(random.choice([0,1,2,3]))) if data_packet_delivery_count == data_packet_delivery_count_previous: #checking if the data packet delivery has stagnated n_attempts_counter += 1 if n_attempts_counter > n_attempts: #get out of the data channel as it seems that the other node is still trying to rendezvous mode = "sync" continue else: data_packet_delivery_count_previous = 0 data_packet_delivery_count = 0 data_packet_delivery_count_previous = data_packet_delivery_count ch_energy = tb.rxpath.probe.level() #check if primary user is present if int(ch_energy) > 1.8e8: #if primary user is there then dont transmit on this channel stop_time = datetime.now() _elapsed_time = start_time - stop_time elapsed_time = _elapsed_time.seconds print "\n[[ Primary User Detected: Evacuating Current Channel ]]\n" print "\n[[ Scanning channels for network nodes ]]\n" mode = "sync" return_flag = 1 if __name__ == '__main__': try: main() except KeyboardInterrupt: pass