def start_sensing(self, samp_num): # broadcast the start command to all the nodes to start # the first round of data collection # Only head can broadcast this command # The node with id = 0 need to report the data after this command print 'start_round_robin' if self.node_type != CLUSTER_HEAD: print 'Only cluster head can start the data collect' return 1 if self.state != HEAD_IDLE and self.state != ROUND_COLLECTED: print 'The sensing can only be initiated when Head is idle state' return 1 pkt_size = struct.pack('!H', 26) # (2) include the pktno(4) fromaddr = struct.pack('!I', HEAD_ADDR) #(4) toaddr = struct.pack('!I', BCST_ADDR) #(4) pkt_type = struct.pack('!B', CTRL_TYPE) #(1) ctrl_cmd = struct.pack('!B', START_SENSE)# (1) current_time = self.tb.source.u.get_time_now().get_real_secs() print '***************************************This round of collection initated at time ', current_time start_time = current_time #0.09s is the switching time of half-duplex print 'start_time = %.7f' %start_time self.current_start_time = start_time start_time = struct.pack('!d', start_time) # (8) samp_num = struct.pack('!H', samp_num) # (2) payload = pkt_size + fromaddr + toaddr + pkt_type + ctrl_cmd + start_time + samp_num self.output.put(payload) print "start_sense =", pkt_utils.string_to_hex_list(payload) self.state = SENSE_START
def send_pkt(self, seqNr, addressInfo, payload='', eof=False): """ Send the payload. @param seqNr: sequence number of packet @type seqNr: byte @param addressInfo: address information for packet @type addressInfo: string @param payload: data to send @type payload: string """ if eof: msg = gr.message(1) # tell self.pkt_input we're not sending any more packets else: FCF = make_FCF() pkt = make_ieee802_15_4_packet(FCF, seqNr, addressInfo, payload, self.pad_for_usrp) print "pkt =", packet_utils.string_to_hex_list(pkt), len(pkt) msg = gr.message_from_string(pkt) self.pkt_input.msgq().insert_tail(msg)
def round_data_collect(self, tran_id, node_id): #usingthe start time as tran_id # broadcast the data collect command to all the node, but only the specified node report if self.node_type != CLUSTER_HEAD: print 'Only cluster head can start the data collect' return 1 if (self.state != SENSE_START and self.state != ROUND_COLLECTING): print 'Round robin data collection can only be performed when SENSE_START or ROUND_COLLECTING state' return 1 pkt_size = struct.pack('!H', 26) # (2) include the pktno(4) fromaddr = struct.pack('!I', HEAD_ADDR) # (4) toaddr = struct.pack('!I', BCST_ADDR) # (4) pkt_type = struct.pack('!B', CTRL_TYPE) # (1) ctrl_cmd = struct.pack('!B', COLLECT_DATA) # (1) node_id = struct.pack('!H', node_id) # (2) tid = struct.pack('!d', tran_id) # (8) payload = pkt_size + fromaddr + toaddr + pkt_type + ctrl_cmd + node_id + tid print 'round robin collect from node ', node_id print "round_collect =", pkt_utils.string_to_hex_list(payload) self.output.put(payload)
def send_pkt(self, seqNr, addressInfo, payload='', eof=False): """ Send the payload. @param seqNr: sequence number of packet @type seqNr: byte @param addressInfo: address information for packet @type addressInfo: string @param payload: data to send @type payload: string """ if eof: msg = gr.message( 1) # tell self.pkt_input we're not sending any more packets else: FCF = make_FCF() pkt = make_ieee802_15_4_packet(FCF, seqNr, addressInfo, payload, self.pad_for_usrp) print "pkt =", packet_utils.string_to_hex_list(pkt), len(pkt) msg = gr.message_from_string(pkt) self.pkt_input.msgq().insert_tail(msg)
def process_payload(self, payload, options): #print 'process_pay_load' length = len(payload) #test code #if length == 12: # time.sleep(0.008) # self.round_data_collect(0, 1) if length <= 17: print 'useless payload' return 1 (pktno, pktsize, fromaddr, toaddr, pkttype) = struct.unpack('!IHIIB', payload[0:15]) if length != pktsize: print 'invalid payload' return 1 ####State Machine For the Cluster Head if self.node_type == "head": if pkttype == DATA_TYPE: rt = self.tb.source.u.get_time_now().get_real_secs() print 'recieve the data at time %.7f' %rt (node_id,) = struct.unpack('!H', payload[15:17]) if self.state == SENSE_START: if node_id == 0 and self.current_rep_id == -1: #Got data from the 1st node #print "incoming_payload =", pkt_utils.string_to_hex_list(payload) rt = self.defragment(payload, node_id) if rt == 0: #Need next packet from the same node return 0 elif rt == 1: #Completed collection of all the framgmented packets self.state = ROUND_COLLECTING elif rt > 1 or rt < 0: #Errors # need to add code to reset all the nodes self.state = HEAD_IDLE return 1 else: print 'incorrect incoming data from node ', node_id # Could broadcast the reset command to reset all the nodes self.state = HEAD_IDLE return 1 elif self.state == ROUND_COLLECTING: if node_id == self.current_rep_id: #print "incoming_payload =", pkt_utils.string_to_hex_list(payload) rt = self.defragment(payload, node_id) if rt == 0: #Need next packet from the same node return 0 elif rt > 1 or rt < 0: #Need to add code for reset the nodes self.state = HEAD_IDLE return 1 #Completed collection of all the fragemented packets if self.current_rep_id >= self.net_size - 1: print "last node has reported data" finish_time = self.tb.sensor.u.get_time_now().get_real_secs() print '***************************************This round of collection started at time %.7f' %(self.current_start_time - 0.09) print '==============================This round collection finished at time %.7f' %finish_time self.state = ROUND_COLLECTED self.current_rep_id = -1 self.current_loop += 1 if self.current_loop < self.loop_number: print 'initiate the next round of sensing' #time.sleep(0.01) self.start_sensing(options.samp_num) self.state = SENSE_START return 0 else: self.current_loop = 0 print 'Complete all rounds of sesning' if self.process_collected_data() == 1: print 'All round of sensing data are processed' self.state = HEAD_IDLE else: print 'Data error' else: print 'incorrect incoming data from node ', node_id self.state = HEAD_IDLE return 1 else: print 'Should not receive data in the current state' self.state = HEAD_IDLE return 1 # If reach here, the state should be ROUND_COLLECTING if self.state == ROUND_COLLECTING: (tran_id,) = struct.unpack('!d', payload[17:25]) # use start time as transaction ID # Collect the data from the next node t = self.tb.sensor.u.get_time_now().get_real_secs() print '------------------------------------------collect next node at time ', t self.current_rep_id = node_id + 1 if self.current_rep_id < self.net_size: time.sleep(0.009) #Maybe here the delay can be ignored as the last node don't need to receive it. self.round_data_collect(tran_id, self.current_rep_id) else: # should not reach here print 'error in report node id' return 1 ####State machine for the CLuster Node: elif self.node_type == "node": rt = self.tb.sensors[0].u.get_time_now().get_real_secs() print 'recieve the commnad at time %.7f' %rt #print "incoming_command =", pkt_utils.string_to_hex_list(payload) if pkttype == CTRL_TYPE: (ctrl_cmd,) = struct.unpack('!B', payload[15:16]) print 'pkttype == CTRL_TYPE' if self.state == NODE_IDLE: print '-->NODE_IDLE' if ctrl_cmd == START_SENSE: # start sensing received print 'START_SENSE received' self.state = SENSING print '----->SENSING' (start_time, samp_num) = struct.unpack('!dH', payload[16:26]) self.current_start_time = start_time print "self.current_start_time = ", pkt_utils.string_to_hex_list(payload[16:24]) self.current_samp_num = samp_num print 'samp_num = ', samp_num print 'start_time = %.7f' %(start_time + 0.7) # start the data collection as specified time #sensor_time = self.sensor.u.get_time_now().get_real_secs() #print 'sensor_time = %.7f' %sensor_time #if start_time + 0.015 - sensor_time > 0: for i in range(len(self.sensors)): self.sensors[i].u.set_start_time(uhd.time_spec_t(start_time+0.70)) #started later 0.070s # Start data collecting if (STREAM_OR_FINITE == 1): #finite acqusition samp_num = int(10*options.sx_samprate) current_t = self.sensor.u.get_time_now().get_real_secs() print 'current time = %.7f' %current_t self.samps = self.sensor.u.finite_acquisition(samp_num) if len(self.samps) == 0: print 'no samps captured' self.state = NODE_IDLE return 0 elif (STREAM_OR_FINITE == 0): #streaming data collection #start streaming here for i in range(len(self.sensors)): self.sensors[i].u.start() #start the timer self.sense_timer = threading.Timer(STREAM_TIME, self.stop_sensing) self.sense_timer.start() self.state = SENSING return 0 # the data report will be done in timer expiring callback #o_samps = np.array(np.real(self.samps[int(0.5*options.sx_samprate):])) #o_samps.astype('float64').tofile(self.fd) #print 'samps len = ', len(self.samps) #compute the covariance matrix #mat = [] #l_v = 64 #for i in range(len(self.samps) - l_v + 1): # v = [] # for j in range(l_v): # v.append(abs(self.samps[i + j])) # mat.append(v) #matx = np.array(mat).T #covmat = np.cov(matx) #trace_cov = np.trace(covmat) #print 'trace is ', trace_cov if self.node_id == 0: # for node 0, just report the data to head print 'begin reporting data, data per pkt = ', options.data_pkt #time.sleep(0.01) #Don't need to delay due to the sensing time plus the sensing delay there #test code #self.send_test_data() #return 0 if self.report_data(self.samps, self.node_id, samp_num, options.data_pkt) == 1: print 'error in reporting data' return 1 self.state = NODE_IDLE print '------>NODE_IDLE' else: self.state = WAIT_REPORT print '------>WAIT_REPORT' else: print 'Recieved incorrect cmd in NODE_IDLE state' return 1 elif self.state == WAIT_REPORT: print '---->WAIT_REPORT' if ctrl_cmd == COLLECT_DATA: print 'COLLECT_DATA received' (node_id, ) = struct.unpack('!H', payload[16:18]) if node_id == self.node_id: print 'begin reporting data, data per pkt = ', options.data_pkt #time.sleep(0.004) #Here we need a delay to ensure the cluster head switched to receiving #test code #self.send_test_data() #return 0 self.report_data(self.samps, self.node_id, self.current_samp_num, options.data_pkt) self.state = NODE_IDLE else: print 'Received incorrect cmd in WAIT_REPORT state' elif self.state == SENSING: #only reset command accepted, not added yet print 'Only Reset command accepted at this state, not implemented' else: print "error node type" return 0