def __init__(self, input_ = None): ''' @param input_: Cadena de 1 y 0's (opcional espacioes), cadena de caracteres tal cual vienen del socket, entero (32bits) o lista de enteros. ''' if not input_: self.__bf = bitfield(0) elif type(input_) == str: # Es una cadena binara? if all(map(lambda c: c in '01 ', input_)): input_ = input_.replace(' ', '') i = int(input_, 2) self.__bf = bitfield(i) # cadena normal, tal cual sacada del socket else: self.__bf = bitfield([ ord(c) for c in input_]) elif type(input_) == int or type(input_) is long: self.__bf = bitfield(input_) elif type(input_) == list and all(map(lambda i: type(i) is int, input_)): self.__bf = bitfield(input_) else: raise ValueError('No se puede crear DTime a partir de %s' % input_)
def __init__(self, input_=None): ''' @param input_: Cadena de 1 y 0's (opcional espacioes), cadena de caracteres tal cual vienen del socket, entero (32bits) o lista de enteros. ''' if not input_: self.__bf = bitfield(0) elif type(input_) == str: # Es una cadena binara? if all(map(lambda c: c in '01 ', input_)): input_ = input_.replace(' ', '') i = int(input_, 2) self.__bf = bitfield(i) # cadena normal, tal cual sacada del socket else: self.__bf = bitfield([ord(c) for c in input_]) elif type(input_) == int or type(input_) is long: self.__bf = bitfield(input_) elif type(input_) == list and all(map(lambda i: type(i) is int, input_)): self.__bf = bitfield(input_) else: raise ValueError('No se puede crear DTime a partir de %s' % input_)
def crear_control(cls, origen, destino, secuencia, puerto = None, bit = None, estado = None, es_comando_indirecto = False): ''' Si comando es 1, entocnes es una indirección. El tercer byte no se tiene en cuenta. ''' p = cls() p['SOF'] = SOF p['QTY'] = 10 # Este ya lo sabemos p['DST'] = destino p['SRC'] = origen p['SEQ'] = secuencia p['COM'] = COMANDOS['CONTROL'] byte_0, byte_1 = bitfield(0), bitfield(0) # Es comando byte_0[7] = es_comando_indirecto and 1 or 0 # 2 ^ 6 = 64 puertos byte_0[0:6] = puerto # Setear el bit a 1 o a 0 byte_1[3] = estado if not es_comando_indirecto: # el nible superior no se utiliza byte_1[0:3] = bit p['A00'] = int(byte_0) p['A01'] = int(byte_1) p['BCH'], p['BCL'] = cls.generar_checksum(p) return p
def _parse_packet(self, packet_bytes): ''' Parse a raw udp packet and return a list of parsed messages. ''' byte_buffer = ByteBuffer(packet_bytes) parsed_messages = [] while not byte_buffer.is_empty(): message_id, sequence_number, message_flags = \ byte_buffer.read_struct(self.MESSAGE_TRANSPORT_HEADER) message_type_id = messages.BaseMessage.read_header_from_byte_buffer( byte_buffer)[0] message = self.message_factory.get_by_id(message_type_id)() message.read_from_byte_buffer(byte_buffer) # - These flags are for consumption by .update() message_flags_bf = bitfield(message_flags) message.is_reliable = message_flags_bf[1] message.is_ordered = message_flags_bf[0] message.sequence_number = sequence_number message.message_id = message_id parsed_messages.append(message) return parsed_messages
def _pack_tuc(part_list, **args): ''' @arg part_list: Argumento de entrada salida ''' byte = bitfield(0) byte[6:8] = args['tipo'] byte[0:6] = args['uc'] part_list.append(int(byte))
def _pack_pbe(part_list, **args): ''' @arg part_list: Argumento de entrada salida ''' byte = bitfield(0) byte[0] = args['status'] byte[1:4] = args['bit'] byte[4:8] = args['port'] part_list.append(int(byte))
def _parse_bytes(self): ''' Parsea la entrada basandose en self.cadena. Este método debe ser sobrecargado en las subclases en el caso de cambiar la decodificación de evento. ''' # Primera parte bf = bitfield(self.cadena[0]) self.tipo, self.uc = bf[6:8], bf[0:6] # Segunda parte bf = bitfield(self.cadena[1]) self.port, self.bit, self.event = bf[4:8], bf[1:4], bf[0:1] bf = bitfield(self.cadena[2:6]) # Cuatro bytes de fecha self.y, self.d, self.h, self.s = bf[26:32], bf[17:26], bf[12:17], bf[0:12] self.cseg, self.dseg = self.cadena[6:8] self.microsceconds = self.dseg * 10000 + self.cseg * 100
def _parse_bytes(self): ''' Parsea la entrada basandose en self.cadena. Este método debe ser sobrecargado en las subclases en el caso de cambiar la decodificación de evento. ''' # Primera parte bf = bitfield(self.cadena[0]) self.tipo, self.uc = bf[6:8], bf[0:6] # Segunda parte bf = bitfield(self.cadena[1]) self.port, self.bit, self.event = bf[4:8], bf[1:4], bf[0:1] bf = bitfield(self.cadena[2:6]) # Cuatro bytes de fecha self.y, self.d, self.h, self.s = bf[26:32], bf[17:26], bf[12:17], bf[ 0:12] self.cseg, self.dseg = self.cadena[6:8] self.microsceconds = self.dseg * 10000 + self.cseg * 100
def crear_control(cls, origen, destino, secuencia, puerto=None, bit=None, estado=None, es_comando_indirecto=False): ''' Si comando es 1, entocnes es una indirección. El tercer byte no se tiene en cuenta. ''' p = cls() p['SOF'] = SOF p['QTY'] = 10 # Este ya lo sabemos p['DST'] = destino p['SRC'] = origen p['SEQ'] = secuencia p['COM'] = COMANDOS['CONTROL'] byte_0, byte_1 = bitfield(0), bitfield(0) # Es comando byte_0[7] = es_comando_indirecto and 1 or 0 # 2 ^ 6 = 64 puertos byte_0[0:6] = puerto # Setear el bit a 1 o a 0 byte_1[3] = estado if not es_comando_indirecto: # el nible superior no se utiliza byte_1[0:3] = bit p['A00'] = int(byte_0) p['A01'] = int(byte_1) p['BCH'], p['BCL'] = cls.generar_checksum(p) return p
def _pack_date(part_list, **args): ''' @arg part_list: Argumento de entrada salida ''' # Creamos un bitfield para la fecha, este va a ser de 32 bits bytes = bitfield(0) date_time = args['date_time'] bytes[26:32] = date_time.year - 2000 # Año desde el 2000 bytes[17:26] = date_time.date().timetuple()[7] # Dia del año bytes[12:17] = date_time.hour bytes[00:12] = date_time.minute * 60 + date_time.second # Separamos los bytes init_tope = list(range_2_pot(32)) init_tope.reverse() for init, tope in init_tope: part_list.append(int(bytes[init:tope])) # Dmseg y cDmseg part_list.append(args['cseg'] % 100) part_list.append(args['dmseg'] % 100)
def send_message(self, message, ordered=False, reliable=False): ''' Send a message and specify any options for the send method used. A message sent inOrder is implicitly sent as reliable. message is an instance of a subclass of packets.BasePacket. Returns the number of bytes added to the output queue for this message (header + message). ''' self._last_send_timestamp = time.time() self._outgoing_message_id += 1 message_id = self._outgoing_message_id if ordered: self._outgoing_ordered_sequence_number += 1 inorder_sequence_number = self._outgoing_ordered_sequence_number else: inorder_sequence_number = 0 packet_flags = bitfield() packet_flags[0] = int(ordered) packet_flags[1] = int(reliable) message_transport_header = struct.pack( '!' + self.MESSAGE_TRANSPORT_HEADER, message_id, inorder_sequence_number, int(packet_flags)) message_bytes = message.get_packet_bytes() total_length = len(message_bytes) + len(message_transport_header) self._out_bytes += total_length self._add_message_bytes_to_output_list( message_id, message_transport_header + message_bytes, ordered or reliable) self._log.debug('Packet data length = %s' % len(message_bytes)) self._log.debug('Header length = %s' % len(message_transport_header)) self._log.debug('Added %d byte %s packet in outgoing buffer' % (total_length, message.__class__.__name__)) return total_length