def process_byte_rd(self): """method process_kernel_evt(): Form incoming bytes into RZ pkts.""" #buf_len = len(self._rd_buf) if self._rd_state == 0: # searching _rd_buf for for SYNC byte, 0x00 response to LAN_HELLO, OR 0x0253 ACK (latter two must be expected) for i in range(self._bytes_read): if self._rd_buf[self._rd_buf_start_idx] == 0x16: self._rd_state = 1 break self._rd_buf_start_idx = (self._rd_buf_start_idx + 1) & 0xFF self._rd_buf_cur_idx = self._rd_buf_start_idx if self._rd_state != 1: # failed to find even a single SYNC in given byte buffer, so stay at State 0 print 'No SYNC found in recv buffer:' recvd_bytes = array.array('B', '\0' * self._bytes_read) idx = self._rd_buf_start_idx - self._bytes_read for i in range(self._bytes_read): recvd_bytes[i] = self._rd_buf[idx] idx = (idx + 1) & 0xFF print_array_as_hex(recvd_bytes) del recvd_bytes return buf_len = (self._rd_buf_end_idx - self._rd_buf_start_idx) & 0xFF if self._rd_state == 1: if buf_len >= 2: # looking for SOH byte after SYNC if self._rd_buf[(self._rd_buf_start_idx + 1) & 0xFF] == 0x01: self._rd_state = 2 else: self._rd_state = 0 return else: return if self._rd_state == 2: if buf_len >= self._pkt_hdr_len: # waiting for remainder of hdr # Make a copy of the nominal pkt: pkt = array.array('B', '\0' * self._pkt_hdr_len) for i in range(self._pkt_hdr_len): idx = (self._rd_buf_start_idx + i) & 0xFF pkt[i] = self._rd_buf[idx] if pkt[self._pkt_type_idx] == 0x00: print 'H', else: print '.', sys.stdout.flush() #print_array_as_hex(pkt) chksum_calc = checksum(pkt, 2, self._pkt_hdr_len - 2) # do not use SYNC/SOH or chksum itself in calc chksum_given = pkt[self._pkt_hdr_len - 1] if chksum_calc == chksum_given: # Get packet type and determine whether or not to expect an extension: ext = pkt[self._pkt_type_idx] & LAN_EXTENDED if ext: #self._pkt_ext_len = ((self._rd_buf[self._pkt_data_idx] << 8) + self._rd_buf[self._pkt_data_idx + 1]) & 0xC000 #self._total_pkt_len = self._pkt_hdr_len + self._pkt_ext_len #self._rd_state = 3 print 'Extended pkts not supported yet!' self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF return else: # Finished receiving this header-only pkt recvd from the RS485 port, # so process it: self._total_pkt_len = self._pkt_hdr_len #pkt = self._rd_buf[:self._total_pkt_len] self.process_rd_pkt(pkt) # @fixme: Rtn value could have a pkt to pass to RouterThread to send on to other interface #self._rd_buf = self._rd_buf[self._total_pkt_len:] # trim processed pkt bytes from start of _rd_buf self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF del pkt return else: # checksum failed, so try to deal with possible causes gracefully #@fixme Scan contents of read buffer for more instances of SYNC/SOH # header which might be starts of true pkt headers. print 'Calc checksum %02x does not match pkt hdr checksum %02x:' % (chksum_calc, chksum_given) print_array_as_hex(self._rd_buf[:self._pkt_hdr_len]) self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF return else: return
class PortMonThr(Thread): """class PortMonThr: Test one-thread-per-port performance on RS485 networks. """ _pkt_hdr_len = 14 _pkt_type_idx = 10 _pkt_data_idx = 11 _pkt_dst_idx = 2 _pkt_src_idx = 6 _pkt_hdr_chksum_idx = 13 def __init__(self, ir_node): """method __init__(): Parameter 'ir_node' is a ref to an instance of an RzvcIfRouteNode.""" Thread.__init__(self) self._ir_node = ir_node self._file = self._ir_node._file self._fd = self._ir_node._file.fileno() self._poll_obj = None self.go = 1 self._rd_buf_len = 256 self._rd_buf = array.array('B', '\0' * self._rd_buf_len) self._rd_buf_start_idx = 0 # holds index of first byte in (potential) pkt self._rd_buf_cur_idx = 0 # holds index of current byte in buffer (logically, if not physically, between start and end) self._rd_buf_end_idx = 0 # holds index of last byte read self._bytes_read = 0 self._rd_state = 0 # start the subclass reading state machine in the 1st state self._pkt_ext_len = 0 # set to non-zero in transition from State 2 to State 3, if any for a given pkt self._total_pkt_len = 0 # sum of _pkt_hdr_len and _pkt_ext_len for any given pkt self._ser_num = 30000 # 0x7530: choose higher number than expected from regular Mozaic, RZ100, or Tessera; @fixme: what about multi-Mediator systems? # Prepare to send pkts by breaking _ser_num into component bytes: self._ser_num_bytes = long_to_bytes(self._ser_num) self._low_rzc = sys.maxint # listen for and store lowest dst/src address self._high_rzc = 0 # listen for and store highest dst/src address def run(self): self.debug_print(' runs on %s.' % currentThread(), 0) # Create one-and-only poll object: self._poll_obj = select.poll() # Register one-and-only fd for input events: self._fd = self._ir_node._file.fileno() # in case it changed without de/reconstruction of this thread obj self._poll_obj.register(self._fd, select.POLLIN) # Enter thread's main loop: total_bytes = 0 avg_bytes_per_loop = 0 loop_count = 0 total_loop_time = 0 avg_loop_time = 0 macro_cnt = 500 byte_threshold = 1000 self.go = 1 # set to '0' only by other threads that want to stop this thread start_time = time.clock() while self.go: loop_count = loop_count + 1 if (total_bytes > byte_threshold): temp_time = time.clock() macro_loop_time = temp_time - start_time #print 'macro_loop_time = ', macro_loop_time, 'temp_time = ', temp_time, 'start_time = ', start_time start_time = temp_time avg_loop_time = macro_loop_time / loop_count avg_bytes_per_loop = total_bytes / loop_count loop_count = 0 # reset total_bytes = 0 # reset burden = avg_loop_time / avg_bytes_per_loop #print 'avg_loop_time = ', avg_loop_time, 'avg_bytes_per_loop = ', avg_bytes_per_loop, 'burden per byte = ', burden # Enter the one-and-only wait state used by this RouterThread: evt_pairs = self._poll_obj.poll() self.debug_print('Event pairs received = %s' % evt_pairs, 1) # If no event pairs are returned by poll(), then an error must have occurred: if len(evt_pairs) == 0: self.debug_print('Timeout error detected for fd %d, %s.' % self._fd, 1) # Else, process event pairs: else: for evt_pair in evt_pairs: # Submit the kernel event(s) to the generating IW for processing, # and act on the result: if evt_pair[1] == select.POLLIN: rd_str = self._file.read() total_bytes = total_bytes + len(rd_str) self._bytes_read = len(rd_str) for i in range(self._bytes_read): self._rd_buf[self._rd_buf_end_idx] = ord(rd_str[i]) self._rd_buf_end_idx = (self._rd_buf_end_idx + 1) & 0xFF self.process_byte_rd() else: raise EInvalidValue('Event Type', evt_pair[1]) self._poll_obj.unregister(self._fd) self.debug_print('on %s is ending run()...' % currentThread(), 0) def process_byte_rd(self): """method process_kernel_evt(): Form incoming bytes into RZ pkts.""" #buf_len = len(self._rd_buf) if self._rd_state == 0: # searching _rd_buf for for SYNC byte, 0x00 response to LAN_HELLO, OR 0x0253 ACK (latter two must be expected) for i in range(self._bytes_read): if self._rd_buf[self._rd_buf_start_idx] == 0x16: self._rd_state = 1 break self._rd_buf_start_idx = (self._rd_buf_start_idx + 1) & 0xFF self._rd_buf_cur_idx = self._rd_buf_start_idx if self._rd_state != 1: # failed to find even a single SYNC in given byte buffer, so stay at State 0 print 'No SYNC found in recv buffer:' recvd_bytes = array.array('B', '\0' * self._bytes_read) idx = self._rd_buf_start_idx - self._bytes_read for i in range(self._bytes_read): recvd_bytes[i] = self._rd_buf[idx] idx = (idx + 1) & 0xFF print_array_as_hex(recvd_bytes) del recvd_bytes return buf_len = (self._rd_buf_end_idx - self._rd_buf_start_idx) & 0xFF if self._rd_state == 1: if buf_len >= 2: # looking for SOH byte after SYNC if self._rd_buf[(self._rd_buf_start_idx + 1) & 0xFF] == 0x01: self._rd_state = 2 else: self._rd_state = 0 return else: return if self._rd_state == 2: if buf_len >= self._pkt_hdr_len: # waiting for remainder of hdr # Make a copy of the nominal pkt: pkt = array.array('B', '\0' * self._pkt_hdr_len) for i in range(self._pkt_hdr_len): idx = (self._rd_buf_start_idx + i) & 0xFF pkt[i] = self._rd_buf[idx] if pkt[self._pkt_type_idx] == 0x00: print 'H', else: print '.', sys.stdout.flush() #print_array_as_hex(pkt) chksum_calc = checksum(pkt, 2, self._pkt_hdr_len - 2) # do not use SYNC/SOH or chksum itself in calc chksum_given = pkt[self._pkt_hdr_len - 1] if chksum_calc == chksum_given: # Get packet type and determine whether or not to expect an extension: ext = pkt[self._pkt_type_idx] & LAN_EXTENDED if ext: #self._pkt_ext_len = ((self._rd_buf[self._pkt_data_idx] << 8) + self._rd_buf[self._pkt_data_idx + 1]) & 0xC000 #self._total_pkt_len = self._pkt_hdr_len + self._pkt_ext_len #self._rd_state = 3 print 'Extended pkts not supported yet!' self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF return else: # Finished receiving this header-only pkt recvd from the RS485 port, # so process it: self._total_pkt_len = self._pkt_hdr_len #pkt = self._rd_buf[:self._total_pkt_len] self.process_rd_pkt(pkt) # @fixme: Rtn value could have a pkt to pass to RouterThread to send on to other interface #self._rd_buf = self._rd_buf[self._total_pkt_len:] # trim processed pkt bytes from start of _rd_buf self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF del pkt return else: # checksum failed, so try to deal with possible causes gracefully #@fixme Scan contents of read buffer for more instances of SYNC/SOH # header which might be starts of true pkt headers. print 'Calc checksum %02x does not match pkt hdr checksum %02x:' % (chksum_calc, chksum_given) print_array_as_hex(self._rd_buf[:self._pkt_hdr_len]) self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF return else: return if self._rd_state == 3: # waiting for extension if buf_len >= self._total_pkt_len: # waiting for remainder of extension chksum_calc = checksum(self._rd_buf, self._pkt_hdr_len, self._total_pkt_len - 2) chksum_given = self._rd_buf[self._total_pkt_len - 1] if chksum_calc == chksum_given: # Finished receiving this header/ext pkt from the RS485 port, so process it: pkt = self._rd_buf[:self._total_pkt_len] self.process_rd_pkt(pkt) # @fixme: Rtn value could have a pkt to pass to RouterThread to send on to other interface self._rd_buf = self._rd_buf[self._total_pkt_len:] # trim processed pkt bytes from start of _rd_buf else: # checksum failed, so try to deal with possible causes gracefully #@fixme Scan contents of read buffer for more instances of SYNC/SOH # header which might be starts of true pkt headers. print 'Calc checksum %02x does not match pkt extension checksum %02x:' % (chksum_calc, chksum_given) print_array_as_hex(self._rd_buf[:self._total_pkt_len]) self._rd_buf = self._rd_buf[self._total_pkt_len:] # don't delete any bytes from subsequent pkts self._rd_state = 0 self._pkt_ext_len = 0 self._total_pkt_len = 0 return else: raise EInvalidValue('RzvcIfWrap Substate', str(self._rd_state)) return
def run(self): self.debug_print(' runs on %s.' % currentThread(), 0) # Create one-and-only poll object: self._poll_obj = select.poll() poll_obj = self._poll_obj # Register each port's fd to correlate with incoming bytes for poll() triggering: iws_list = self._iws.values( ) # extract list of values from local IW dict for iw in iws_list: poll_obj.register(iw._file.fileno(), select.POLLIN) # Enter thread's main loop: total_bytes = 0 avg_bytes_per_loop = 0 loop_count = 0 total_loop_time = 0 avg_loop_time = 0 macro_cnt = 2000 self.go = 1 # set to '0' only by other threads that want to stop this thread start_time = time.clock() while self.go: loop_count = loop_count + 1 if ((loop_count % macro_cnt) == 0): temp_time = time.clock() macro_loop_time = temp_time - start_time print 'macro_loop_time = ', macro_loop_time, 'temp_time = ', temp_time, 'start_time = ', start_time start_time = temp_time avg_loop_time = macro_loop_time / macro_cnt burden = avg_loop_time / avg_bytes_per_loop print 'avg_loop_time = ', avg_loop_time, 'avg_bytes_per_loop = ', avg_bytes_per_loop, 'burden per byte = ', burden #@fixme: Set timeouts: timeout_msec = -1 # Enter the one-and-only wait state used by this RouterThread: self.debug_print('timeout_msec = %d' % timeout_msec, 0) evt_pairs = poll_obj.poll(timeout_msec) self.debug_print('Event pairs received = %s' % evt_pairs, 0) # If no event pairs are returned by poll(), then a timeout must have occurred: if len(evt_pairs) == 0: if not self._timeout_iw: self.debug_print( 'Programming Error. poll() timed out without any responsible InterfaceWrapper!', 0) raise EInvalidValue self.debug_print( 'Timeout detected for fd %d, %s.' % (self._timeout_iw._file.fileno(), self._timeout_iw), 1) result = self._timeout_iw.handle_timeout(self._timeout_param) if result == 'erase': self._erase( self._timeout_iw, 'Timeout caused scan of data_skt %d, and it looks dead.' ) self._timeout_iw = None self._timeout_param = None # Else, process event pairs: else: for evt_pair in evt_pairs: # Obtain the signaled IW from the local dict: try: iw_rd = self._iws[evt_pair[0]] except KeyError: # erasure ops below may have removed IW responsible for given evt_pair self.debug_print( 'Ignoring event pair for closed fd %d' % evt_pair[0], 0) continue # Submit the kernel event(s) to the generating IW for processing, # and act on the result: result = iw_rd.process_kernel_evt(evt_pair[1]) cmd = result[0] if not cmd: continue elif cmd == 'send': # Give iw_rd ref to Router, get back list of IWs to which to send # reading IW's buffer: iws_dest = self._router.send(iw_rd) wr_buf = result[1] total_bytes = total_bytes + len(wr_buf) avg_bytes_per_loop = total_bytes / loop_count if len(iws_dest) == 0: continue for iw_dest in iws_dest: if iw_dest._file.fileno() < 0: print 'Program error: IW %s has fd %d! Already closed/deleted!' % ( iw_dest, iw_dest._file.fileno()) continue try: iw_dest.write(wr_buf) print 'Sent pkt to %d' % iw_dest._file.fileno() except: # destination IW may have been closed already... print 'Failed to write to fd %d: %s, %s' % ( iw_dest._file.fileno(), sys.exc_type, sys.exc_value) #self._erase(iw_dest, 'Failed to write to fd %d.') continue # If debugging, send notification of xmitted bytes to console: self.debug_print( 'Xmitted byte array from fd %d:' % iw_rd._file.fileno(), 0) if debug_lvl > 1: print_array_as_hex(iw_rd._rd_buf) iw_rd._rd_buf = array.array( 'B') # clear the read buf of the current IW elif cmd == 'new_iw': # We have another data_skt to poll, so register it and add it into the local dict: new_iw = result[1] data_skt_fd = new_iw._file.fileno() self._iws[data_skt_fd] = new_iw self._router.add_interface_wrap(new_iw) poll_obj.register(data_skt_fd, select.POLLIN) self.debug_print( 'Input event on listen_skt %d => data_skt %d.' % (iw_rd._file.fileno(), data_skt_fd), 0) continue # connection established, but no data to process yet elif cmd == 'mon_iw': # We have a data_skt from which to echo incoming bytes/pkts: self._mon_skt = result[1] data_skt_fd = self._mon_skt._file.fileno() self._iws[data_skt_fd] = self._mon_skt self._router.add_interface_wrap(self._mon_skt) poll_obj.register( data_skt_fd, select.POLLIN ) # no input expected from this mon_skt (yet), but be prepared... self.debug_print( 'Input event on listen_skt %d => mon_skt %d.' % (iw_rd._file.fileno(), data_skt_fd), 0) continue # connection established elif cmd == 'erase': # IW determined it was not worthy of existence, so squish it: self._erase(iw_rd, result[1]) continue else: self.debug_print( 'Unknown result from InterfaceWrap.process_kernel_evt(): %s' % str(result), 0) raise EInvalidValue( 'Result from InterfaceWrap.process_kernel_evt()', str(result)) # Unregister all of the fd's in the local dict from the poll() machinery: iw_fds_list = self._iws.keys() for iw_fd in iw_fds_list: poll_obj.unregister(iw_fd) self.debug_print('on %s is ending run()...' % currentThread(), 0)
continue else: self.debug_print( 'Unknown result from InterfaceWrap.process_kernel_evt(): %s' % str(result), 0) raise EInvalidValue( 'Result from InterfaceWrap.process_kernel_evt()', str(result)) # Unregister all of the fd's in the local dict from the poll() machinery: iw_fds_list = self._iws.keys() for iw_fd in iw_fds_list: poll_obj.unregister(iw_fd) self.debug_print('on %s is ending run()...' % currentThread(), 0) def debug_print(self, msg, msg_lvl): if msg_lvl < debug_lvl: prn_msg = 'RouterThread: ' + msg print prn_msg if __name__ == '__main__': print 'RouterThread.py: Starting Unit Test...' a = array.array('B', [16, 24, 56, 255]) print_array_as_hex(a, 16) print 'RouterThread.py: Unit Test completed.' pass
def run(self): self.debug_print(' runs on %s.' % currentThread(), 0) # Create one-and-only poll object: self._poll_obj = select.poll() poll_obj = self._poll_obj # Register each port's fd to correlate with incoming bytes for poll() triggering: iws_list = self._iws.values() # extract list of values from local IW dict for iw in iws_list: poll_obj.register(iw._file.fileno(), select.POLLIN) # Enter thread's main loop: total_bytes = 0 avg_bytes_per_loop = 0 loop_count = 0 total_loop_time = 0 avg_loop_time = 0 macro_cnt = 2000 self.go = 1 # set to '0' only by other threads that want to stop this thread start_time = time.clock() while self.go: loop_count = loop_count + 1 if ((loop_count % macro_cnt) == 0): temp_time = time.clock() macro_loop_time = temp_time - start_time print 'macro_loop_time = ', macro_loop_time, 'temp_time = ', temp_time, 'start_time = ', start_time start_time = temp_time avg_loop_time = macro_loop_time / macro_cnt burden = avg_loop_time / avg_bytes_per_loop print 'avg_loop_time = ', avg_loop_time, 'avg_bytes_per_loop = ', avg_bytes_per_loop, 'burden per byte = ', burden #@fixme: Set timeouts: timeout_msec = -1 # Enter the one-and-only wait state used by this RouterThread: self.debug_print('timeout_msec = %d' % timeout_msec, 0) evt_pairs = poll_obj.poll(timeout_msec) self.debug_print('Event pairs received = %s' % evt_pairs, 0) # If no event pairs are returned by poll(), then a timeout must have occurred: if len(evt_pairs) == 0: if not self._timeout_iw: self.debug_print('Programming Error. poll() timed out without any responsible InterfaceWrapper!', 0) raise EInvalidValue self.debug_print('Timeout detected for fd %d, %s.' % (self._timeout_iw._file.fileno(), self._timeout_iw), 1) result = self._timeout_iw.handle_timeout(self._timeout_param) if result == 'erase': self._erase(self._timeout_iw, 'Timeout caused scan of data_skt %d, and it looks dead.') self._timeout_iw = None self._timeout_param = None # Else, process event pairs: else: for evt_pair in evt_pairs: # Obtain the signaled IW from the local dict: try: iw_rd = self._iws[evt_pair[0]] except KeyError: # erasure ops below may have removed IW responsible for given evt_pair self.debug_print('Ignoring event pair for closed fd %d' % evt_pair[0], 0) continue # Submit the kernel event(s) to the generating IW for processing, # and act on the result: result = iw_rd.process_kernel_evt(evt_pair[1]) cmd = result[0] if not cmd: continue elif cmd == 'send': # Give iw_rd ref to Router, get back list of IWs to which to send # reading IW's buffer: iws_dest = self._router.send(iw_rd) wr_buf = result[1] total_bytes = total_bytes + len(wr_buf) avg_bytes_per_loop = total_bytes / loop_count if len(iws_dest) == 0: continue for iw_dest in iws_dest: if iw_dest._file.fileno() < 0: print 'Program error: IW %s has fd %d! Already closed/deleted!' % (iw_dest, iw_dest._file.fileno()) continue try: iw_dest.write(wr_buf) print 'Sent pkt to %d' % iw_dest._file.fileno() except: # destination IW may have been closed already... print 'Failed to write to fd %d: %s, %s' % (iw_dest._file.fileno(), sys.exc_type, sys.exc_value) #self._erase(iw_dest, 'Failed to write to fd %d.') continue # If debugging, send notification of xmitted bytes to console: self.debug_print('Xmitted byte array from fd %d:' % iw_rd._file.fileno(), 0) if debug_lvl > 1: print_array_as_hex(iw_rd._rd_buf) iw_rd._rd_buf = array.array('B') # clear the read buf of the current IW elif cmd == 'new_iw': # We have another data_skt to poll, so register it and add it into the local dict: new_iw = result[1] data_skt_fd = new_iw._file.fileno() self._iws[data_skt_fd] = new_iw self._router.add_interface_wrap(new_iw) poll_obj.register(data_skt_fd, select.POLLIN) self.debug_print('Input event on listen_skt %d => data_skt %d.' % (iw_rd._file.fileno(), data_skt_fd), 0) continue # connection established, but no data to process yet elif cmd == 'mon_iw': # We have a data_skt from which to echo incoming bytes/pkts: self._mon_skt = result[1] data_skt_fd = self._mon_skt._file.fileno() self._iws[data_skt_fd] = self._mon_skt self._router.add_interface_wrap(self._mon_skt) poll_obj.register(data_skt_fd, select.POLLIN) # no input expected from this mon_skt (yet), but be prepared... self.debug_print('Input event on listen_skt %d => mon_skt %d.' % (iw_rd._file.fileno(), data_skt_fd), 0) continue # connection established elif cmd == 'erase': # IW determined it was not worthy of existence, so squish it: self._erase(iw_rd, result[1]) continue else: self.debug_print('Unknown result from InterfaceWrap.process_kernel_evt(): %s' % str(result), 0) raise EInvalidValue('Result from InterfaceWrap.process_kernel_evt()', str(result)) # Unregister all of the fd's in the local dict from the poll() machinery: iw_fds_list = self._iws.keys() for iw_fd in iw_fds_list: poll_obj.unregister(iw_fd) self.debug_print('on %s is ending run()...' % currentThread(), 0)
self.debug_print('Input event on listen_skt %d => mon_skt %d.' % (iw_rd._file.fileno(), data_skt_fd), 0) continue # connection established elif cmd == 'erase': # IW determined it was not worthy of existence, so squish it: self._erase(iw_rd, result[1]) continue else: self.debug_print('Unknown result from InterfaceWrap.process_kernel_evt(): %s' % str(result), 0) raise EInvalidValue('Result from InterfaceWrap.process_kernel_evt()', str(result)) # Unregister all of the fd's in the local dict from the poll() machinery: iw_fds_list = self._iws.keys() for iw_fd in iw_fds_list: poll_obj.unregister(iw_fd) self.debug_print('on %s is ending run()...' % currentThread(), 0) def debug_print(self, msg, msg_lvl): if msg_lvl < debug_lvl: prn_msg = 'RouterThread: ' + msg print prn_msg if __name__ == '__main__': print 'RouterThread.py: Starting Unit Test...' a = array.array('B', [16, 24, 56, 255]) print_array_as_hex(a, 16) print 'RouterThread.py: Unit Test completed.' pass
def process_byte_rd(self): """method process_kernel_evt(): Form incoming bytes into RZ pkts.""" # buf_len = len(self._rd_buf) if ( self._rd_state == 0 ): # searching _rd_buf for for SYNC byte, 0x00 response to LAN_HELLO, OR 0x0253 ACK (latter two must be expected) for i in range(self._bytes_read): if self._rd_buf[self._rd_buf_start_idx] == 0x16: self._rd_state = 1 break self._rd_buf_start_idx = (self._rd_buf_start_idx + 1) & 0xFF self._rd_buf_cur_idx = self._rd_buf_start_idx if self._rd_state != 1: # failed to find even a single SYNC in given byte buffer, so stay at State 0 print "No SYNC found in recv buffer:" recvd_bytes = array.array("B", "\0" * self._bytes_read) idx = self._rd_buf_start_idx - self._bytes_read for i in range(self._bytes_read): recvd_bytes[i] = self._rd_buf[idx] idx = (idx + 1) & 0xFF print_array_as_hex(recvd_bytes) del recvd_bytes return buf_len = (self._rd_buf_end_idx - self._rd_buf_start_idx) & 0xFF if self._rd_state == 1: if buf_len >= 2: # looking for SOH byte after SYNC if self._rd_buf[(self._rd_buf_start_idx + 1) & 0xFF] == 0x01: self._rd_state = 2 else: self._rd_state = 0 return else: return if self._rd_state == 2: if buf_len >= self._pkt_hdr_len: # waiting for remainder of hdr # Make a copy of the nominal pkt: pkt = array.array("B", "\0" * self._pkt_hdr_len) for i in range(self._pkt_hdr_len): idx = (self._rd_buf_start_idx + i) & 0xFF pkt[i] = self._rd_buf[idx] if pkt[self._pkt_type_idx] == 0x00: print "H", else: print ".", sys.stdout.flush() # print_array_as_hex(pkt) chksum_calc = checksum(pkt, 2, self._pkt_hdr_len - 2) # do not use SYNC/SOH or chksum itself in calc chksum_given = pkt[self._pkt_hdr_len - 1] if chksum_calc == chksum_given: # Get packet type and determine whether or not to expect an extension: ext = pkt[self._pkt_type_idx] & LAN_EXTENDED if ext: # self._pkt_ext_len = ((self._rd_buf[self._pkt_data_idx] << 8) + self._rd_buf[self._pkt_data_idx + 1]) & 0xC000 # self._total_pkt_len = self._pkt_hdr_len + self._pkt_ext_len # self._rd_state = 3 print "Extended pkts not supported yet!" self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF return else: # Finished receiving this header-only pkt recvd from the RS485 port, # so process it: self._total_pkt_len = self._pkt_hdr_len # pkt = self._rd_buf[:self._total_pkt_len] self.process_rd_pkt( pkt ) # @fixme: Rtn value could have a pkt to pass to RouterThread to send on to other interface # self._rd_buf = self._rd_buf[self._total_pkt_len:] # trim processed pkt bytes from start of _rd_buf self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF del pkt return else: # checksum failed, so try to deal with possible causes gracefully # @fixme Scan contents of read buffer for more instances of SYNC/SOH # header which might be starts of true pkt headers. print "Calc checksum %02x does not match pkt hdr checksum %02x:" % (chksum_calc, chksum_given) print_array_as_hex(self._rd_buf[: self._pkt_hdr_len]) self._rd_state = 0 self._rd_buf_start_idx = (self._rd_buf_start_idx + self._pkt_hdr_len) & 0xFF return else: return if self._rd_state == 3: # waiting for extension if buf_len >= self._total_pkt_len: # waiting for remainder of extension chksum_calc = checksum(self._rd_buf, self._pkt_hdr_len, self._total_pkt_len - 2) chksum_given = self._rd_buf[self._total_pkt_len - 1] if chksum_calc == chksum_given: # Finished receiving this header/ext pkt from the RS485 port, so process it: pkt = self._rd_buf[: self._total_pkt_len] self.process_rd_pkt( pkt ) # @fixme: Rtn value could have a pkt to pass to RouterThread to send on to other interface self._rd_buf = self._rd_buf[self._total_pkt_len :] # trim processed pkt bytes from start of _rd_buf else: # checksum failed, so try to deal with possible causes gracefully # @fixme Scan contents of read buffer for more instances of SYNC/SOH # header which might be starts of true pkt headers. print "Calc checksum %02x does not match pkt extension checksum %02x:" % (chksum_calc, chksum_given) print_array_as_hex(self._rd_buf[: self._total_pkt_len]) self._rd_buf = self._rd_buf[self._total_pkt_len :] # don't delete any bytes from subsequent pkts self._rd_state = 0 self._pkt_ext_len = 0 self._total_pkt_len = 0 return else: raise EInvalidValue("RzvcIfWrap Substate", str(self._rd_state)) return