class IsmtvModule(wishful_module.AgentModule): node = None sensor = None sweep_config = None generator = None tx_config = None def __init__(self, dev): super(IsmtvModule, self).__init__() self.log = logging.getLogger('IsmtvModule') ser = serial.Serial(dev, 115200) self.node = alh.ALHTerminal(ser) @wishful_module.bind_function(upis.radio.get_measurements) def get_measurements(self, params): if not self.sensor: self.sensor = SpectrumSensor(self.node) config_list = self.sensor.get_config_list() self.sweep_config = config_list.get_sweep_config( params[0], params[1], params[2]) if self.sweep_config is None: self.sensor = None raise Exception("Node can not scan specified frequency range.") sweep = self.sensor.sweep(self.sweep_config) f = list(self.sweep_config.get_hz_list()) p = sweep.data return {'frequency': f, 'power': p} @wishful_module.bind_function(upis.radio.play_waveform) def play_waveform(self, iface, freq, power_lvl, kwargs): if not self.generator: self.generator = SignalGenerator(self.node) config_list = self.generator.get_config_list() self.tx_config = config_list.get_tx_config(freq, power_lvl) if self.tx_config is None: self.generator = None return 2 now = time.time() program = SignalGeneratorProgram(self.tx_config, now + 5, kwargs['play_time']) self.generator.program(program) return 0 @wishful_module.bind_function(upis.radio.get_radio_info) def get_radio_info(self, platform_id): if platform_id == "sensor": sensor = SpectrumSensor(self.node) config_list = sensor.get_config_list() elif platform_id == "generator": generator = SignalGenerator(self.node) config_list = generator.get_config_list() else: config_list = str( platform_id) + ": Not supported! Try: sensor or generator" return config_list
def get_radio_info(self, platform_id): if platform_id == "sensor": sensor = SpectrumSensor(self.node) config_list = sensor.get_config_list() elif platform_id == "generator": generator = SignalGenerator(self.node) config_list = generator.get_config_list() else: config_list = str(platform_id) + ": Not supported! Try: sensor or generator" return config_list
def __init__(self, txnode, rxnode): # We set up the SignalGenerator and SpectrumSensor objects here # for later use. We also query both nodes for their # corresponding lists of available hardware configurations. # # Since hardware will not change during the experiment, we only # do the query once in object constructor. This makes repeated # measurements faster. self.generator = SignalGenerator(txnode) self.generator_cl = self.generator.get_config_list() self.sensor = SpectrumSensor(rxnode) self.sensor_cl = self.sensor.get_config_list()
def play_waveform(self, iface, freq, power_lvl, kwargs): if not self.generator: self.generator = SignalGenerator(self.node) config_list = self.generator.get_config_list() self.tx_config = config_list.get_tx_config(freq, power_lvl) if self.tx_config is None: self.generator = None return 2 now = time.time() program = SignalGeneratorProgram(self.tx_config, now + 5, kwargs['play_time']) self.generator.program(program) return 0
def setGeneratorConfigurationChannel(self, fCh, powerDBm): """Set configuration for signal generation. fHz -- Frequency to generate. powerDBm -- Transmission power. """ self.generatorNode = SignalGenerator(self.node) generatorConfigList = self.generatorNode.get_config_list() self.txConfig = TxConfig(generatorConfigList.get_config(0, 0), fCh, powerDBm) if self.txConfig is None: raise Exception("Something went wrong with configuration, txConfig is None.")
def main(): # Turn on logging so that we can see ALH requests happening in the # background. logging.basicConfig(level=logging.INFO) coor = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", 10001) # Node 16 is equipped with an 2.4 GHz tranceiver (CC2500 on # SNE-ISMTV-24) that is capable of transmitting on the 2.4 GHz ISM # band. node = alh.ALHProxy(coor, 16) # We the ALHProxy object with a SignalGenerator object that provides an # convenient interface to the signal generation functionality. generator = SignalGenerator(node) # Get a ConfigList object that contains a list of device configurations # supported by the chosen transmitter node. config_list = generator.get_config_list() # ConfigList.get_tx_config() method will automatically choose # a device and hardware configuration that can be used to transmit on # the requested frequency. It returns an instance of TxConfig class # that describes all settings for signal generation. # # We request a transmission at 2.425 GHz with 0 dBm. tx_config = config_list.get_tx_config(2425e6, 0) if tx_config is None: raise Exception( "Node can not transmit at the specified frequency and/or power.") # SignalGeneratorProgram object joins the transmit config with timing # information. Here we specify that we want to start the transmission 5 # seconds from now and that the transmission should be 30 seconds long. now = time.time() program = SignalGeneratorProgram(tx_config, now + 5, 30) generator.program(program)
def main(): # Turn on logging so that we can see ALH requests happening in the # background. logging.basicConfig(level=logging.INFO) coor = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", 10001) # Node 16 is equipped with an 2.4 GHz tranceiver (CC2500 on # SNE-ISMTV-24) that is capable of transmitting on the 2.4 GHz ISM # band. node = alh.ALHProxy(coor, 16) # We the ALHProxy object with a SignalGenerator object that provides an # convenient interface to the signal generation functionality. generator = SignalGenerator(node) # Get a ConfigList object that contains a list of device configurations # supported by the chosen transmitter node. config_list = generator.get_config_list() # ConfigList.get_tx_config() method will automatically choose # a device and hardware configuration that can be used to transmit on # the requested frequency. It returns an instance of TxConfig class # that describes all settings for signal generation. # # We request a transmission at 2.425 GHz with 0 dBm. tx_config = config_list.get_tx_config(2425e6, 0) if tx_config is None: raise Exception("Node can not transmit at the specified frequency and/or power.") # SignalGeneratorProgram object joins the transmit config with timing # information. Here we specify that we want to start the transmission 5 # seconds from now and that the transmission should be 30 seconds long. now = time.time() program = SignalGeneratorProgram(tx_config, now + 5, 30) generator.program(program)
def main(): coor_industrial_zone = alh.ALHWeb(get_communicator_url(), 10001) time_start = time.time() + 30 # Set up transmissions for node_id in [10, 8, 7]: node = alh.ALHProxy(coor_industrial_zone, node_id) node.post("prog/firstCall", "1") su1 = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 10)) su2 = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 8)) mic = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 7)) config_list = su1.get_config_list() tx_config = config_list.get_tx_config(0, 0) mic.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=790e6, power_dbm=0), time_start=time_start+30, time_duration=40) ) mic.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=807e6, power_dbm=0), time_start=time_start+80, time_duration=40) ) su1.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=787e6, power_dbm=0), time_start=time_start, time_duration=35) ) su1.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=780e6, power_dbm=0), time_start=time_start+35, time_duration=90) ) su2.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=795e6, power_dbm=0), time_start=time_start, time_duration=35) ) su2.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=800e6, power_dbm=0), time_start=time_start+35, time_duration=50) ) su2.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=797e6, power_dbm=0), time_start=time_start+85, time_duration=35) ) # Set up spectrum sensing sensor_node_ids = [ 19 ] sensor_nodes = [ alh.ALHProxy(coor_industrial_zone, id) for id in sensor_node_ids ] sensors = [ SpectrumSensor(sensor_node) for sensor_node in sensor_nodes ] config_list = sensors[0].get_config_list() sweep_config = config_list.get_sweep_config( start_hz=770000000, stop_hz=820000000, step_hz=400000) # -1 below is a work-around for an off-by-one error somewhere in the spectrum sensing # resource handler sweep_config.num_channels -= 1 program = SpectrumSensorProgram(sweep_config, time_start, time_duration=120, slot_id=5) for sensor in sensors: sensor.program(program) # Wait for the experiment to finish for sensor in sensors: while not sensor.is_complete(program): sys.stderr.write("waiting...\n") time.sleep(2) if time.time() > (program.time_start + program.time_duration + 30): raise Exception("Something went wrong") sys.stderr.write("experiment is finished. retrieving data.\n") result = sensor.retrieve(program) try: os.mkdir("data") except OSError: pass result.write("data/node_%d.dat" % (sensor.alh.addr,))
class NodePair(object): # Object constructor takes two nodes: Node doing the signal # transmission and node doing power measurements. def __init__(self, txnode, rxnode): # We set up the SignalGenerator and SpectrumSensor objects here # for later use. We also query both nodes for their # corresponding lists of available hardware configurations. # # Since hardware will not change during the experiment, we only # do the query once in object constructor. This makes repeated # measurements faster. self.generator = SignalGenerator(txnode) self.generator_cl = self.generator.get_config_list() self.sensor = SpectrumSensor(rxnode) self.sensor_cl = self.sensor.get_config_list() # This method performs the power measurement. f_hz parameter is the # central frequency in hertz on which the channel measurement will be done. # ptx_dbm is the transmission power in dbm. If ptx_dbm is None, then # the transmitting node will remain silent. def measure(self, f_hz, ptx_dbm): now = time.time() if ptx_dbm is not None: # If transmission was requested, setup the transmitter. tx_config = self.generator_cl.get_tx_config(f_hz, ptx_dbm) if tx_config is None: raise Exception("Node can not scan specified frequency range.") generator_p = SignalGeneratorProgram(tx_config, now + 1, 14) self.generator.program(generator_p) # Setup the receiver for power measurement at the same # frequency as the transmitter. We will only sense a single # frequency, hence both start and stop parameters of the sweep # are set to f_hz. sweep_config = self.sensor_cl.get_sweep_config(f_hz, f_hz, 400e3) if sweep_config is None: raise Exception("Node can not scan specified frequency range.") sensor_p = SpectrumSensorProgram(sweep_config, now + 3, 10, 1) self.sensor.program(sensor_p) # Note that the transmit interval is longer than the receive # interval: # # now + 1 + 3 / + 13 + 15 # | tx start rx start \ rx stop tx stop # | | | / | | # | | |===========\===========| | # | | receive / | | # | | \ | # | |======================/======================| # transmit # # This is to make sure that signal transmission is happening # during the whole time the receiver is measuring signal power. # Start times may differ +/- 1 second due to unsynchronized # clocks and management network latency. while not self.sensor.is_complete(sensor_p): print "waiting..." time.sleep(2) # Retrieve the data and return a single vector with power # measurements (in dBm) from the sensing node. result = self.sensor.retrieve(sensor_p) return np.array(result.get_data())[:, 0] # This method calculates the channel gain between the nodes. def get_channel_gain(self, f_hz, ptx_dbm): def db_to_mw(db): return 10.**(db / 10.) def mw_to_db(mw): return 10. * np.log10(mw) # First, measure just the noise level on the receiving node. # Transmitter is turned off. pnoise_dbm = self.measure(f_hz, None) # Second, measure the received signal power level with the # transmitter turned on. prx_dbm = self.measure(f_hz, ptx_dbm) # Convert all power values to linear scale. ptx_mw = db_to_mw(ptx_dbm) pnoise_mw = db_to_mw(pnoise_dbm) prx_mw = db_to_mw(prx_dbm) # Take the mean of both noise and received signal power # measurements. pnoise_mw_mean = np.mean(pnoise_mw) prx_mw_mean = np.mean(prx_mw) print "p_noise = %.1f dBm (mean=%e mW std=%e mW)" % ( mw_to_db(pnoise_mw_mean), pnoise_mw_mean, np.std(pnoise_mw)) print "p_rx = %.1f dBm (mean=%e mW std=%e mW)" % ( mw_to_db(prx_mw_mean), prx_mw_mean, np.std(prx_mw)) # Use the mean values to estimate the channel gain. h_mean = (prx_mw_mean - pnoise_mw_mean) / ptx_mw # Convert back to logarithmic scale. h_mean_db = mw_to_db(h_mean) print "h = %.1f dB" % (h_mean_db, ) return h_mean_db
def main(): coor_industrial_zone = alh.ALHWeb(get_communicator_url(), 10001) time_start = time.time() + 15 # Set up transmissions cognitive_terminal = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 25)) config_list = cognitive_terminal.get_config_list() device_config = config_list.get_config(0, 0) cognitive_terminal.program( SignalGeneratorProgram( TxConfig(device_config, 110, 0), time_start=(time_start+5), time_duration=25)) cognitive_terminal.program( SignalGeneratorProgram( TxConfig(device_config, 225, 0), time_start=(time_start+32), time_duration=23)) legacy_terminal = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 16)) legacy_terminal.program( SignalGeneratorProgram( TxConfig(device_config, 114, 0), time_start=(time_start+25), time_duration=30)) # Set up spectrum sensing sensor_node_ids = [ 2, 17, 6 ] sensor_nodes = [ alh.ALHProxy(coor_industrial_zone, id) for id in sensor_node_ids ] sensors = [ SpectrumSensor(sensor_node) for sensor_node in sensor_nodes ] config_list = sensors[0].get_config_list() sweep_config = config_list.get_config(0, 0).get_full_sweep_config() program = SpectrumSensorProgram(sweep_config, time_start, time_duration=60, slot_id=5) for sensor in sensors: sensor.program(program) # Wait for the experiment to finish for sensor in sensors: while not sensor.is_complete(program): print "waiting..." time.sleep(2) if time.time() > (program.time_start + program.time_duration + 60): raise Exception("Something went wrong") print "experiment is finished. retrieving data." result = sensor.retrieve(program) try: os.mkdir("data") except OSError: pass result.write("data/node_%d.dat" % (sensor.alh.addr,))
def main(): # Turn on logging so that we can see ALH requests happening in the # background. logging.basicConfig(level=logging.INFO) coor = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", 10001) # Nodes 16 and 17 are equipped with an 2.4 GHz tranceiver (CC2500 on # SNE-ISMTV-24) that is capable of transmitting and receiving on the # 2.4 GHz ISM band. node16 = alh.ALHProxy(coor, 16) node17 = alh.ALHProxy(coor, 17) # We will use node 16 as a signal generator. We wrap its ALHProxy # object with a SignalGenerator object for convenience. generator = SignalGenerator(node16) # Set up a transmission configuration for 2.425 GHz and 0 dBm generator_config_list = generator.get_config_list() tx_config = generator_config_list.get_tx_config(2425e6, 0) if tx_config is None: raise Exception("Node can not scan specified frequency range.") # We will use node 17 as a spectrum sensor. Again, we wrap it with a # SpectrumSensor object for convenience. sensor = SpectrumSensor(node17) # We set up a frequency sweep configuration covering 2.40 GHz to 2.45 # GHz band with 400 kHz steps. sensor_config_list = sensor.get_config_list() sweep_config = sensor_config_list.get_sweep_config(2400e6, 2450e6, 400e3) if sweep_config is None: raise Exception("Node can not scan specified frequency range.") # Take note of current time. now = time.time() # SignalGeneratorProgram and SpectrumSensorProgram objects allow us to # program signal generation and spectrum sensing tasks in advance. # # In this case, we setup a signal generation task using the # configuration we prepared above starting 10 seconds from now and # lasting for 20 seconds. # # Similarly for spectrum sensing, we setup a task using frequency sweep # we prepared above starting 5 seconds from now and lasting for 30 # seconds. Results of the measurement will be stored in slot 4. generator_program = SignalGeneratorProgram(tx_config, now + 10, 20) sensor_program = SpectrumSensorProgram(sweep_config, now + 5, 30, 4) # Now actually send instructions over the management network to nodes # in the testbed. generator.program(generator_program) sensor.program(sensor_program) # Query the spectrum sensing node and wait until the task has been # completed. while not sensor.is_complete(sensor_program): print "waiting..." time.sleep(2) # Retrieve spectrum sensing results. This might take a while since the # management mesh network is slow. result = sensor.retrieve(sensor_program) # Write results into a CSV file. result.write("06-programmed-tasks.dat")
def main(): # Turn on logging so that we can see requests and responses in the # terminal. This is useful to keep track of what is going on during the # experiment. logging.basicConfig(level=logging.INFO) # We must first create an object representing the coordinator node. # Each cluster in the LOG-a-TEC has its own coordinator and all # communication with the nodes must go through it. # # The parameters used here correspond to the LOG-a-TEC City Center # out-door cluster (see LOG-a-TEC documentation for other valid # options). # # Note that you must have a valid user name and password saved in an # "alhrc" file in order for this to work. See vesna-alh-tools README # for instructions on how to do that. # # Also make sure you reserved the cluster in the calendar before # running the experiment! coor = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", 10002) # We will be using node 45 in this example. First we create a generic # node object for it. node = alh.ALHProxy(coor, 45) # We will use our node as a signal generator. Here, we wrap the generic # node object with the SignalGenerator class that provides a convenient # interface to the signal generation capabilities of the node's radio # hardware. generator = SignalGenerator(node) # Request the list of signal generation configurations that the node # supports. # # Node 45 is equipped with a SNE-ISMTV-2400 radio board that contains a # CC2500 reconfigurable transceiver. This tranceiver currently supports # one configuration in the 2.4 GHz ISM band. gen_config_list = generator.get_config_list() # Let's print the list out in a nice format for future reference. print print "Signal generation devices and configurations available" print "======================================================" print gen_config_list print # For a demonstration, we'll transmit a random signal at 2.425 GHz and # 0 dBm. We create a TxConfig object that describes the transmission. tx_config = gen_config_list.get_tx_config(2425e6, 0) if tx_config is None: raise Exception("Node can not transmit at the specified frequency and/or power.") # Take note of current time. now = time.time() # SignalGeneratorProgram object allows us to program a node to perform a # signal generation task in advance. We'll setup a task for transmission # parameters we selected above, starting 5 seconds from now and lasting # for 10 seconds. gen_program = SignalGeneratorProgram(tx_config, now + 5, 10) # Finally, we actually send the programming instructions over the testbed's # management network to the node. generator.program(gen_program)
def main(): # Turn on logging so that we can see requests and responses in the # terminal. logging.basicConfig(level=logging.INFO) # We must first create an object representing the coordinator node. coor_campus = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", 9501) # Our experiment will start 15 seconds into the future - this should # give us plenty of time to set up everything. time_start = time.time() + 15 # First we set up the two transmitting nodes: # # Node 53 in the LOG-a-TEC Campus Zone will be playing the role of # the cognitive terminal. cognitive_terminal = SignalGenerator(alh.ALHProxy(coor_campus, 53)) # All nodes we will be using are equipped with SNE-ISMTV-2400 radio # boards with CC2500 transceivers. From the available list of # signal generation configurations supported by this hardware, we # choose the first one: It allows to transmit in 200 kHz wide channels. config_list = cognitive_terminal.get_config_list() device_config = config_list.get_config(0, 0) # Here we program the "cognitive_terminal" node to transmit for 25 # seconds on channel 110 (2422.0 MHz) and then change to channel 225 # (2445.0 MHz). Transmission power is set to 0 dBm. cognitive_terminal.program( SignalGeneratorProgram(TxConfig(device_config, 110, 0), time_start=(time_start + 5), time_duration=25)) cognitive_terminal.program( SignalGeneratorProgram(TxConfig(device_config, 225, 0), time_start=(time_start + 32), time_duration=23)) # Node 54 in the LOG-a-TEC Campus Zone will be playing the role of # the legacy terminal. legacy_terminal = SignalGenerator(alh.ALHProxy(coor_campus, 54)) # The legacy terminal, lacking the capability to change channels on # demand, is programmed to just transmit for 30 seconds on channel 114 # (2422.8 MHz) legacy_terminal.program( SignalGeneratorProgram(TxConfig(device_config, 114, 0), time_start=(time_start + 25), time_duration=30)) # Now we setup some sensing nodes so that we can observe the # transmissions from different points in the testbed. # We will use nodes 51 and 58 for this purpose. sensor_node_ids = [51, 58] sensor_nodes = [alh.ALHProxy(coor_campus, id) for id in sensor_node_ids] sensors = [SpectrumSensor(sensor_node) for sensor_node in sensor_nodes] # For sensing, we will use the first sensing configuration (255 # channels starting at 2.4 GHz with 400 kHz bandwidth) config_list = sensors[0].get_config_list() sweep_config = config_list.get_config(0, 0).get_full_sweep_config() # We instruct the nodes to perform spectrum sensing for 60 seconds. program = SpectrumSensorProgram(sweep_config, time_start, time_duration=60, slot_id=5) for sensor in sensors: sensor.program(program) # All nodes have been programmed at this point - wait for the experiment to finish. for sensor in sensors: while not sensor.is_complete(program): print "waiting..." time.sleep(2) if time.time() > (program.time_start + program.time_duration + 60): raise Exception("Something went wrong") print "experiment is finished. retrieving data." result = sensor.retrieve(program) # We will save the sensing results in a "data/" subdirectory. # Create it, if it doesn't already exist. try: os.mkdir("data") except OSError: pass # For each sensing node, we write the results into a CSV file. # The CSV file can be easily imported and plotted into tools # like MatLab. For example, to plot the recorded spectrogram # using GNU Plot, use the following commands: # # gnuplot> set pm3d map # gnuplot> set xlabel "frequency [MHz]" # gnuplot> set ylabel "time [s]" # gnuplot> set cblabel "power [dBm]" # gnuplot> unset key # gnuplot> splot "node17.csv" using ($2/1e6):1:3 result.write("data/node_%d.csv" % (sensor.alh.addr, ))
def main(): coor_industrial_zone = alh.ALHWeb(get_communicator_url(), 10001) time_start = time.time() + 30 # Set up transmissions for node_id in [10, 8, 7]: node = alh.ALHProxy(coor_industrial_zone, node_id) node.post("prog/firstCall", "1") su1 = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 10)) su2 = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 8)) mic = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 7)) config_list = su1.get_config_list() tx_config = config_list.get_tx_config(0, 0) mic.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=790e6, power_dbm=0), time_start=time_start+30, time_duration=40) ) mic.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=807e6, power_dbm=0), time_start=time_start+80, time_duration=40) ) su1.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=787e6, power_dbm=0), time_start=time_start, time_duration=35) ) su1.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=780e6, power_dbm=0), time_start=time_start+35, time_duration=90) ) su2.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=795e6, power_dbm=0), time_start=time_start, time_duration=35) ) su2.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=800e6, power_dbm=0), time_start=time_start+35, time_duration=50) ) su2.program( SignalGeneratorProgram( config_list.get_tx_config(f_hz=797e6, power_dbm=0), time_start=time_start+85, time_duration=35) ) # Set up spectrum sensing sensor_node_ids = [ 19 ] sensor_nodes = [ alh.ALHProxy(coor_industrial_zone, id) for id in sensor_node_ids ] sensors = [ SpectrumSensor(sensor_node) for sensor_node in sensor_nodes ] config_list = sensors[0].get_config_list() sweep_config = config_list.get_sweep_config( start_hz=770000000, stop_hz=820000000, step_hz=400000) # -1 below is a work-around for an off-by-one error somewhere in the spectrum sensing # resource handler sweep_config.num_channels -= 1 program = SpectrumSensorProgram(sweep_config, time_start, time_duration=120, slot_id=5) for sensor in sensors: sensor.program(program) # Wait for the experiment to finish for sensor in sensors: while not sensor.is_complete(program): print "waiting..." time.sleep(2) if time.time() > (program.time_start + program.time_duration + 30): raise Exception("Something went wrong") print "experiment is finished. retrieving data." result = sensor.retrieve(program) try: os.mkdir("data") except OSError: pass result.write("data/node_%d.dat" % (sensor.alh.addr,))
def main(): # Turn on logging so that we can see requests and responses in the # terminal. logging.basicConfig(level=logging.INFO) # We must first create an object representing the coordinator node. coor_industrial_zone = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", 10001) # Our experiment will start 15 seconds into the future - this should # give us plenty of time to set up everything. time_start = time.time() + 15 # First we set up the two transmitting nodes: # # Node 25 in the LOG-a-TEC Industrial Zone will be playing the role of # the cognitive terminal. cognitive_terminal = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 25)) # All nodes we will be using are equipped with SNE-ISMTV-2400 radio # boards with CC2500 transceivers. From the available list of # signal generation configurations supported by this hardware, we # choose the first one: It allows to transmit in 200 kHz wide channels. config_list = cognitive_terminal.get_config_list() device_config = config_list.get_config(0, 0) # Here we program the "cognitive_terminal" node to transmit for 25 # seconds on channel 110 (2422.0 MHz) and then change to channel 225 # (2445.0 MHz). Transmission power is set to 0 dBm. cognitive_terminal.program( SignalGeneratorProgram( TxConfig(device_config, 110, 0), time_start=(time_start+5), time_duration=25)) cognitive_terminal.program( SignalGeneratorProgram( TxConfig(device_config, 225, 0), time_start=(time_start+32), time_duration=23)) # Node 16 in the LOG-a-TEC Industrial Zone will be playing the role of # the legacy terminal. legacy_terminal = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 16)) # The legacy terminal, lacking the capability to change channels on # demand, is programmed to just transmit for 30 seconds on channel 114 # (2422.8 MHz) legacy_terminal.program( SignalGeneratorProgram( TxConfig(device_config, 114, 0), time_start=(time_start+25), time_duration=30)) # Now we setup some sensing nodes so that we can observe the # transmissions from different points in the testbed. # We will use nodes 2, 17 and 6 for this purpose. sensor_node_ids = [ 2, 17, 6 ] sensor_nodes = [ alh.ALHProxy(coor_industrial_zone, id) for id in sensor_node_ids ] sensors = [ SpectrumSensor(sensor_node) for sensor_node in sensor_nodes ] # For sensing, we will use the first sensing configuration (255 # channels starting at 2.4 GHz with 400 kHz bandwidth) config_list = sensors[0].get_config_list() sweep_config = config_list.get_config(0, 0).get_full_sweep_config() # We instruct the nodes to perform spectrum sensing for 60 seconds. program = SpectrumSensorProgram(sweep_config, time_start, time_duration=60, slot_id=5) for sensor in sensors: sensor.program(program) # All nodes have been programmed at this point - wait for the experiment to finish. for sensor in sensors: while not sensor.is_complete(program): print "waiting..." time.sleep(2) if time.time() > (program.time_start + program.time_duration + 60): raise Exception("Something went wrong") print "experiment is finished. retrieving data." result = sensor.retrieve(program) # We will save the sensing results in a "data/" subdirectory. # Create it, if it doesn't already exist. try: os.mkdir("data") except OSError: pass # For each sensing node, we write the results into a CSV file. # The CSV file can be easily imported and plotted into tools # like MatLab. For example, to plot the recorded spectrogram # using GNU Plot, use the following commands: # # gnuplot> set pm3d map # gnuplot> set xlabel "frequency [MHz]" # gnuplot> set ylabel "time [s]" # gnuplot> set cblabel "power [dBm]" # gnuplot> unset key # gnuplot> splot "node17.csv" using ($2/1e6):1:3 result.write("data/node_%d.csv" % (sensor.alh.addr,))
class GameNode: # transmitting and receiving configurations sweepConfig = None txConfig = None # reference to sensor and generator objects sensorNode = None generatorNode = None def __init__(self, coordinatorId, nodeId, showLog=True): """node constructor Keywords arguments: coordinatorId -- Numerical cluster id. nodeId -- id number of node. """ # get coordinator object self.coordinator = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", coordinatorId) # get node object self.node = alh.ALHProxy(self.coordinator, nodeId) # save Ids self.coordinatorId = coordinatorId self.nodeId = nodeId if showLog: logging.basicConfig(level=logging.INFO) def nodeTest(self): """Print a string if node is active""" print self.node.get("sensor/mcuTemp") def coordinatorTest(self): """Print a string if coordinator is active""" print self.coordinator.get("hello") def getNodeID(self): return self.nodeId def getSenseConfig(self): """just get a configuration list so I can see it""" SpectrumSensor(self).get_config_list() def getGeneratorConfig(self): """just get a configuration list so I can see it""" SignalGenerator(self).get_config_list() def setSenseConfiguration(self, startFreqHz, endFreqHz, stepFerqHz): """Set sensing configuration. Measure the power in frequency band [startFrewHz, endFreqHz] with a predefined step. startFreqHz -- Lower bound of the frequency band to check (inclusive) endFreqHz -- Upper bound of the frequency band to check (inclusive) stepFerqHz -- Frequency step """ self.sensorNode = SpectrumSensor(self.node) sensorConfigList = self.sensorNode.get_config_list() self.sweepConfig = sensorConfigList.get_sweep_config(startFreqHz, endFreqHz, stepFerqHz) if self.sweepConfig is None: raise Exception("Something went wrong with the sweepConfig. sweepConfig is None") def setSenseConfigurationChannel(self, startCh, endCh, stepCh): """Set sensing configuration. Measure the power from start_ch to stop_ch with predefined step startCh -- Lowest frequency channel to sweep endCh -- One past the highest frequency channel to sweep stepCh -- How many channels in a step """ self.sensorNode = SpectrumSensor(self.node) sensorConfigList = self.sensorNode.get_config_list() self.sweepConfig = SweepConfig(sensorConfigList.get_config(0, 0), startCh, endCh, stepCh) if self.sweepConfig is None: raise Exception("Something went wrong with the sweepConfig. sweepConfig is None") def setSenseConfigurationFuulSweep(self): """Set sensing configuration. This method will sense the entire band that device supports. """ self.sensorNode = SpectrumSensor(self.node) sensorConfigList = self.sensorNode.get_config_list() # self.sweepConfig = SpectrumSensor(self.node).get_config_list().get_config(0,0).get_full_sweep_config() self.sweepConfig = sensorConfigList.get_config(0, 0).get_full_sweep_config() if self.sweepConfig is None: raise Exception("Something went wrong with the sweepConfig. sweepConfig is None") def senseStart(self, timeStart, timeDuration, slotID): """Start spectrum sensing on node with predefined configuration (self.sweep_config). May perform a few frequency sweeps, depends on the time duration. If sweepConfig is None raise exception. timeStart -- Time to start the task (UNIX timestamp). timeDuration -- Duration of the task in seconds. slotID -- Numerical slot id used for storing measurements. """ if self.sweepConfig is None: print "Cannot start Sensing. Configuration is missing!!" return None # get program object program = SpectrumSensorProgram(self.sweepConfig, timeStart, timeDuration, slotID) # get sensor object and program the node self.sensorNode.program(program) # wait for sensor to finish the job while not self.sensorNode.is_complete(program): print "waiting..." time.sleep(1) if time.time() > (program.time_start + program.time_duration + 60): raise Exception("Something went wrong when sensing") print "Sensing finished, retrieving data." result = self.sensorNode.retrieve(program) # for simplicity save data in a folder try: os.mkdir("./data") except OSError: pass try: os.mkdir("./data/coor_%d" % (self.coordinatorId)) except OSError: pass # write data, overwrite existing file result.write("./data/coor_%d/node_%d.dat" % (self.coordinatorId, self.nodeId)) def senseStartQuick(self): """returns a list : [[frequencies] , [power_dbm]] Starts spectrum sensing on node with predefined configuration (self.sweepConfig). This method will do a quick step. Use this if time is critical! Bandwidth you can measure in this case is limited. This will perform a single frequency step with the sweep method defined in the SpectrumSensor class. If sweepConfig is None raise exception. """ if self.sweepConfig is None: print "Cannot start Sensing. Configuration is missing!!" return None sweep = SpectrumSensor(self.node).sweep(self.sweepConfig) # get frequency list fHz = self.sweepConfig.get_hz_list() dataReceived = [] dataReceived.append(fHz) dataReceived.append(sweep.data) return dataReceived def setGeneratorConfiguration(self, fHz, powerDBm): """Set configuration for signal generation. fHz -- Frequency to generate. powerDBm -- Transmission power. """ self.generatorNode = SignalGenerator(self.node) generatorConfigList = self.generatorNode.get_config_list() self.txConfig = generatorConfigList.get_tx_config(fHz, powerDBm) if self.txConfig is None: raise Exception("Something went wrong with configuration, txConfig is None.") def setGeneratorConfigurationChannel(self, fCh, powerDBm): """Set configuration for signal generation. fHz -- Frequency to generate. powerDBm -- Transmission power. """ self.generatorNode = SignalGenerator(self.node) generatorConfigList = self.generatorNode.get_config_list() self.txConfig = TxConfig(generatorConfigList.get_config(0, 0), fCh, powerDBm) if self.txConfig is None: raise Exception("Something went wrong with configuration, txConfig is None.") def generatorStart(self, timeStart, timeDuration): """Start signal generation with predefined configuration (txConfig). If txConfig is None raise exception. timeStart -- Time when node starts transmitting. timeDuration -- Time for which node is transmitting. """ if self.txConfig is None: print "Cannot start signal generating, configuration is missing" return None # get a program object program = SignalGeneratorProgram(self.txConfig, timeStart, timeDuration) self.generatorNode.program(program)
def main(): coor_industrial_zone = alh.ALHWeb(get_communicator_url(), 10001) time_start = time.time() + 15 # Set up transmissions cognitive_terminal = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 25)) config_list = cognitive_terminal.get_config_list() device_config = config_list.get_config(0, 0) cognitive_terminal.program( SignalGeneratorProgram(TxConfig(device_config, 110, 0), time_start=(time_start + 5), time_duration=25)) cognitive_terminal.program( SignalGeneratorProgram(TxConfig(device_config, 225, 0), time_start=(time_start + 32), time_duration=23)) legacy_terminal = SignalGenerator(alh.ALHProxy(coor_industrial_zone, 16)) legacy_terminal.program( SignalGeneratorProgram(TxConfig(device_config, 114, 0), time_start=(time_start + 25), time_duration=30)) # Set up spectrum sensing sensor_node_ids = [2, 17, 6] sensor_nodes = [ alh.ALHProxy(coor_industrial_zone, id) for id in sensor_node_ids ] sensors = [SpectrumSensor(sensor_node) for sensor_node in sensor_nodes] config_list = sensors[0].get_config_list() sweep_config = config_list.get_config(0, 0).get_full_sweep_config() program = SpectrumSensorProgram(sweep_config, time_start, time_duration=60, slot_id=5) for sensor in sensors: sensor.program(program) # Wait for the experiment to finish for sensor in sensors: while not sensor.is_complete(program): print "waiting..." time.sleep(2) if time.time() > (program.time_start + program.time_duration + 60): raise Exception("Something went wrong") print "experiment is finished. retrieving data." result = sensor.retrieve(program) try: os.mkdir("data") except OSError: pass result.write("data/node_%d.dat" % (sensor.alh.addr, ))
def main(): # Turn on logging so that we can see requests and responses in the # terminal. This is useful to keep track of what is going on during the # experiment. logging.basicConfig(level=logging.INFO) # We must first create an object representing the coordinator node. # Each cluster in the LOG-a-TEC has its own coordinator and all # communication with the nodes must go through it. # # The parameters used here correspond to the LOG-a-TEC City Center # out-door cluster (see LOG-a-TEC documentation for other valid # options). # # Note that you must have a valid user name and password saved in an # "alhrc" file in order for this to work. See vesna-alh-tools README # for instructions on how to do that. # # Also make sure you reserved the cluster in the calendar before # running the experiment! coor = alh.ALHWeb("https://crn.log-a-tec.eu/communicator", 10002) # We will be using node 45 in this example. First we create a generic # node object for it. node = alh.ALHProxy(coor, 45) # We will use our node as a signal generator. Here, we wrap the generic # node object with the SignalGenerator class that provides a convenient # interface to the signal generation capabilities of the node's radio # hardware. generator = SignalGenerator(node) # Request the list of signal generation configurations that the node # supports. # # Node 45 is equipped with a SNE-ISMTV-2400 radio board that contains a # CC2500 reconfigurable transceiver. This tranceiver currently supports # one configuration in the 2.4 GHz ISM band. gen_config_list = generator.get_config_list() # Let's print the list out in a nice format for future reference. print print "Signal generation devices and configurations available" print "======================================================" print gen_config_list print # For a demonstration, we'll transmit a random signal at 2.425 GHz and # 0 dBm. We create a TxConfig object that describes the transmission. tx_config = gen_config_list.get_tx_config(2425e6, 0) if tx_config is None: raise Exception( "Node can not transmit at the specified frequency and/or power.") # Take note of current time. now = time.time() # SignalGeneratorProgram object allows us to program a node to perform a # signal generation task in advance. We'll setup a task for transmission # parameters we selected above, starting 5 seconds from now and lasting # for 10 seconds. gen_program = SignalGeneratorProgram(tx_config, now + 5, 10) # Finally, we actually send the programming instructions over the testbed's # management network to the node. generator.program(gen_program)