def test_eep_remaining(): # Magnetic switch -example status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xD5, 0x08, 0x01, 0x82, 0x5D, 0xAB, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x00, 0x53 ])) assert packet.parse_eep(0x00, 0x01) == ['CO'] # Temperature-example status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x00, 0x00, 0x55, 0x08, 0x01, 0x81, 0xB7, 0x44, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x75 ])) # If this fails, the data is retained from the last Packet parsing! assert packet.parse_eep(0x00, 0x01) == [] # Once we have parse with the correct func and type, this should pass. assert packet.parse_eep(0x02, 0x05) == ['TMP']
def test_switch(): status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xF6, 0x50, 0x00, 0x29, 0x89, 0x79, 0x30, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x9D ])) assert packet.parse_eep(0x02, 0x02) == ['R1', 'EB', 'R2', 'SA', 'T21', 'NU'] assert packet.parsed['SA']['value'] == 'No 2nd action' assert packet.parsed['EB']['value'] == 'pressed' assert packet.parsed['R1']['value'] == 'Button BI' assert packet.parsed['T21']['value'] is True assert packet.parsed['NU']['value'] is True assert packet.learn is True assert packet.status == 0x30 assert packet.repeater_count == 0 status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xF6, 0x00, 0x00, 0x29, 0x89, 0x79, 0x20, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00, 0x03 ])) assert packet.parse_eep(0x02, 0x02) == ['R1', 'EB', 'R2', 'SA', 'T21', 'NU'] assert packet.parsed['SA']['value'] == 'No 2nd action' assert packet.parsed['EB']['value'] == 'released' assert packet.parsed['T21']['value'] is True assert packet.parsed['NU']['value'] is False assert packet.learn is True assert packet.status == 0x20 assert packet.repeater_count == 0
def test_switch(): status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xF6, 0x50, 0x00, 0x29, 0x89, 0x79, 0x30, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x9D ])) assert sorted(p.parse_eep(0x02, 0x04)) == ['EBO', 'R1', 'R2', 'SA'] assert p.parsed['SA']['value'] == 'No 2nd action' assert p.parsed['EBO']['value'] == 'pressed' assert p.parsed['R1']['value'] == 'Button BI' assert p.learn is True status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xF6, 0x00, 0x00, 0x29, 0x89, 0x79, 0x20, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00, 0x03 ])) assert sorted(p.parse_eep(0x02, 0x04)) == ['EBO', 'R1', 'R2', 'SA'] assert p.parsed['SA']['value'] == 'No 2nd action' assert p.parsed['EBO']['value'] == 'released' assert p.learn is True
def test_fails(): status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xD5, 0x08, 0x01, 0x82, 0x5D, 0xAB, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x00, 0x53 ])) eep = EEP() # Mock initialization failure eep.init_ok = False assert eep.find_profile(packet._bit_data, 0xD5, 0x00, 0x01) is None # TODO: Needs better test. A much better. assert eep.set_values(profile=None, data=[True], status=[False, False], properties={'CV': False}) eep.init_ok = True profile = eep.find_profile(packet._bit_data, 0xD5, 0x00, 0x01) assert eep.set_values(profile, packet._bit_data, packet.status, {'ASD': 1}) assert eep.find_profile(packet._bit_data, 0xFF, 0x00, 0x01) is None assert eep.find_profile(packet._bit_data, 0xD5, 0xFF, 0x01) is None assert eep.find_profile(packet._bit_data, 0xD5, 0x00, 0xFF) is None status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x09, 0x07, 0x01, 0x56, 0xD2, 0x04, 0x00, 0x00, 0x01, 0x94, 0xE3, 0xB9, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0xBF ])) assert eep.find_profile(packet._bit_data, 0xD2, 0x01, 0x01) is not None assert eep.find_profile(packet._bit_data, 0xD2, 0x01, 0x01, command=-1) is None
def test_magnetic_switch(): ''' Tests RADIO message for EEP -profile 0xD5 0x00 0x01 ''' status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xD5, 0x08, 0x01, 0x82, 0x5D, 0xAB, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x00, 0x53 ])) assert packet.parse_eep(0x00, 0x01) == ['CO'] assert packet.parsed['CO']['value'] == 'open' assert packet.parsed['CO']['raw_value'] == 0 assert packet.status == 0x00 assert packet.repeater_count == 0 status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xD5, 0x09, 0x01, 0x82, 0x5D, 0xAB, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x00, 0xC7 ])) assert packet.parse_eep(0x00, 0x01) == ['CO'] assert packet.parsed['CO']['value'] == 'closed' assert packet.parsed['CO']['raw_value'] == 1 assert packet.learn is False assert packet.status == 0x00 assert packet.repeater_count == 0
def test_magnetic_switch(): ''' Tests RADIO message for EEP -profile 0xD5 0x00 0x01 ''' status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xD5, 0x08, 0x01, 0x82, 0x5D, 0xAB, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x00, 0x53 ])) assert p.parse_eep(0x00, 0x01) == ['CO'] assert p.parsed['CO']['value'] == 'open' assert p.parsed['CO']['raw_value'] == 0 status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xD5, 0x09, 0x01, 0x82, 0x5D, 0xAB, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x36, 0x00, 0xC7 ])) assert p.parse_eep(0x00, 0x01) == ['CO'] assert p.parsed['CO']['value'] == 'closed' assert p.parsed['CO']['raw_value'] == 1 assert p.learn is False
def test_packet_equals(): data_1 = bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x08, 0x38]) data_2 = bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x08, 0x38]) _, _, packet_1 = Packet.parse_msg(data_1) _, _, packet_2 = Packet.parse_msg(data_2) assert str(packet_1) == '0x%02X %s %s %s' % (packet_1.packet_type, [ hex(o) for o in packet_1.data ], [hex(o) for o in packet_1.optional], packet_1.parsed) assert str(packet_1) == str(packet_2) assert packet_1 == packet_2
def test_fails(): try: Packet.create(PACKET.RESPONSE, 0xA5, 0x01, 0x01) assert False except ValueError: assert True try: Packet.create(PACKET.RADIO_ERP1, 0xA6, 0x01, 0x01) assert False except ValueError: assert True try: Packet.create(PACKET.RADIO_ERP1, 0xA5, 0x01, 0x01, destination='ASDASDASD') assert False except ValueError: assert True try: Packet.create(PACKET.RADIO_ERP1, 0xA5, 0x01, 0x01, sender='ASDASDASD') assert False except ValueError: assert True
def test_packet_equals(): data_1 = bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x08, 0x38]) data_2 = bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x08, 0x38]) _, _, packet_1 = Packet.parse_msg(data_1) _, _, packet_2 = Packet.parse_msg(data_2) assert str(packet_1) == "0x%02X %s %s %s" % ( packet_1.packet_type, [hex(o) for o in packet_1.data], [hex(o) for o in packet_1.optional], packet_1.parsed, ) assert str(packet_1) == str(packet_2) assert packet_1 == packet_2
def test_ute_in(): communicator = Communicator() communicator.base_id = [0xDE, 0xAD, 0xBE, 0xEF] status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x0D, 0x07, 0x01, 0xFD, 0xD4, 0xA0, 0xFF, 0x3E, 0x00, 0x01, 0x01, 0xD2, 0x01, 0x94, 0xE3, 0xB9, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0xAB ]), communicator=communicator) assert packet.sender_hex == '01:94:E3:B9' assert packet.unidirectional is False assert packet.bidirectional is True assert packet.response_expected is True assert packet.number_of_channels == 0xFF assert packet.rorg_manufacturer == 0x3E assert packet.rorg_of_eep == RORG.VLD assert packet.rorg_func == 0x01 assert packet.rorg_type == 0x01 assert packet.teach_in is True assert packet.delete is False assert packet.learn is True assert packet.contains_eep is True response_packet = packet._create_response_packet(communicator.base_id) assert response_packet.sender_hex == 'DE:AD:BE:EF' assert response_packet.destination_hex == '01:94:E3:B9' assert response_packet._bit_data[DB6.BIT_5:DB6.BIT_3] == [False, True] assert response_packet.data[2:7] == packet.data[2:7]
def listen(): jeedom_socket.open() logging.debug("Start listening...") globals.COMMUNICATOR = SerialCommunicator(port=_device) globals.COMMUNICATOR.start() if globals.COMMUNICATOR.base_id is None: logging.error("No base id from enocean key, shutdown") shutdown() logging.info('The Base ID of your controler is %s.' % enocean.utils.to_hex_string( globals.COMMUNICATOR.base_id).replace(':', '')) globals.JEEDOM_COM.send_change_immediate({ 'baseid': str(enocean.utils.to_hex_string(globals.COMMUNICATOR.base_id)).replace( ':', '') }) packet = Packet(PACKET.COMMON_COMMAND, [0x03]) globals.COMMUNICATOR.send(packet) try: thread.start_new_thread(read_socket, ('socket', )) logging.debug('Read Socket Thread Launched') thread.start_new_thread(read_communicator, ('read', )) logging.debug('Read Device Thread Launched') except KeyboardInterrupt: logging.error("KeyboardInterrupt, shutdown") shutdown()
def send_command(self, data, optional, packet_type): """Send a command via the EnOcean dongle.""" from enocean.protocol.packet import Packet packet = Packet(packet_type, data=data, optional=optional) self.hass.helpers.dispatcher.dispatcher_send(SIGNAL_SEND_MESSAGE, packet)
def test_packet_fails(): ''' Tests designed to fail. These include changes to checksum, data length or something like that. ''' fail_examples = ( bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x2B, 0xD2, 0xDD, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x36 ]), bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x2B, 0xD2, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x37 ]), bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x1B, 0xD2, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x36 ]), bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x38]), ) for msg in fail_examples: status, remainder, p = Packet.parse_msg(msg) assert status in [PARSE_RESULT.INCOMPLETE, PARSE_RESULT.CRC_MISMATCH]
def base_id(self): ''' Fetches Base ID from the transmitter, if required. Otherwise returns the currently set Base ID. ''' # If base id is already set, return it. if self._base_id is not None: return self._base_id # Send COMMON_COMMAND 0x08, CO_RD_IDBASE request to the module self.send(Packet(PACKET.COMMON_COMMAND, data=[0x08])) # Loop over 10 times, to make sure we catch the response. # Thanks to timeout, shouldn't take more than a second. # Unfortunately, all other messages received during this time are ignored. for i in range(0, 10): try: packet = self.receive.get(block=True, timeout=0.1) # We're only interested in responses to the request in question. if packet.packet_type == PACKET.RESPONSE and packet.response == RETURN_CODE.OK and len( packet.response_data) == 4: # Base ID is set in the response data. self._base_id = packet.response_data # Put packet back to the Queue, so the user can also react to it if required... self.receive.put(packet) break # Put other packets back to the Queue. self.receive.put(packet) except queue.Empty: continue # Return the current Base ID (might be None). return self._base_id
def test_ute_in(): communicator = Communicator() communicator.base_id = [0xDE, 0xAD, 0xBE, 0xEF] status, buf, packet = Packet.parse_msg( bytearray([ 0x55, 0x00, 0x0D, 0x07, 0x01, 0xFD, 0xD4, 0xA0, 0xFF, 0x3E, 0x00, 0x01, 0x01, 0xD2, 0x01, 0x94, 0xE3, 0xB9, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0xAB ]), communicator=communicator ) assert packet.sender_hex == '01:94:E3:B9' assert packet.unidirectional is False assert packet.bidirectional is True assert packet.response_expected is True assert packet.number_of_channels == 0xFF assert packet.rorg_manufacturer == 0x3E assert packet.rorg_of_eep == RORG.VLD assert packet.rorg_func == 0x01 assert packet.rorg_type == 0x01 assert packet.teach_in is True assert packet.delete is False assert packet.learn is True assert packet.contains_eep is True response_packet = packet._create_response_packet(communicator.base_id) assert response_packet.sender_hex == 'DE:AD:BE:EF' assert response_packet.destination_hex == '01:94:E3:B9' assert response_packet._bit_data[DB6.BIT_5:DB6.BIT_3] == [False, True] assert response_packet.data[2:7] == packet.data[2:7]
def test_event_packet(): data = bytearray([0x55, 0x00, 0x01, 0x00, 0x04, 0x77, 0x01, 0x07]) _, _, packet = Packet.parse_msg(data) assert isinstance(packet, EventPacket) assert packet.event == EVENT_CODE.SA_RECLAIM_NOT_SUCCESFUL assert packet.event_data == [] assert packet.optional == []
def test_send(): ''' Test sending packets to Communicator ''' c = Communicator() assert c.send('AJSNDJASNDJANSD') is False assert c.transmit.qsize() == 0 assert c._get_from_send_queue() is None assert c.send(Packet(PACKET.COMMON_COMMAND, [0x08])) is True assert c.transmit.qsize() == 1 assert isinstance(c._get_from_send_queue(), Packet)
def test_switch(): status, buf, p = Packet.parse_msg( bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xF6, 0x50, 0x00, 0x29, 0x89, 0x79, 0x30, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x9D ])) assert sorted(p.parse_eep(0x02, 0x04)) == ['EBO', 'R1', 'R2', 'SA'] assert p.parsed['SA']['value'] == 'No 2nd action' assert p.parsed['EBO']['value'] == 'pressed' assert p.parsed['R1']['value'] == 'Button BI' assert p.learn is True status, buf, p = Packet.parse_msg( bytearray([ 0x55, 0x00, 0x07, 0x07, 0x01, 0x7A, 0xF6, 0x00, 0x00, 0x29, 0x89, 0x79, 0x20, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00, 0x03 ])) assert sorted(p.parse_eep(0x02, 0x04)) == ['EBO', 'R1', 'R2', 'SA'] assert p.parsed['SA']['value'] == 'No 2nd action' assert p.parsed['EBO']['value'] == 'released' assert p.learn is True
def test_eep_direction(): status, buf, packet = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x32, 0x20, 0x89, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x43 ])) assert packet.parse_eep(0x20, 0x01, 1) == ['CV', 'SO', 'ENIE', 'ES', 'BCAP', 'CCO', 'FTS', 'DWO', 'ACO', 'TMP'] assert packet.parsed['CV']['value'] == 50 assert packet.parse_eep(0x20, 0x01, 2) == ['SP', 'TMP', 'RIN', 'LFS', 'VO', 'VC', 'SB', 'SPS', 'SPN', 'RCU'] assert packet.parsed['SP']['value'] == 50
def parse(self): ''' Parses messages and puts them to receive queue ''' # Loop while we get new messages while True: status, self._buffer, p = Packet.parse_msg(self._buffer) # If message is incomplete -> break the loop if status == PARSE_RESULT.INCOMPLETE: return status # If message is OK, add it to receive queue if status == PARSE_RESULT.OK and p: self.receive.put(p) logger.debug(p)
def test_eep_parsing(): status, buf, packet = Packet.parse_msg( bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x08, 0x28, 0x46, 0x80, 0x01, 0x8A, 0x7B, 0x30, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x49, 0x00, 0x26 ])) assert packet.learn is True assert packet.contains_eep is True assert packet.rorg_func == 0x02 assert packet.rorg_type == 0x05 assert packet.status == 0x00 assert packet.repeater_count == 0
def test_eep_parsing(): status, buf, p = Packet.parse_msg( bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x08, 0x28, 0x46, 0x80, 0x01, 0x8A, 0x7B, 0x30, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x49, 0x00, 0x26 ])) assert p.learn is True assert p.contains_eep is True assert p.rorg_func == 0x02 assert p.rorg_type == 0x05 assert round(p.parsed['TMP']['value'], 1) == 29.0 assert p.parsed['TMP']['raw_value'] == 70
def test_temperature(): ''' Tests RADIO message for EEP -profile 0xA5 0x02 0x05 ''' status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x00, 0x00, 0x55, 0x08, 0x01, 0x81, 0xB7, 0x44, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x75 ])) assert p.parse_eep(0x02, 0x05) == ['TMP'] assert round(p.parsed['TMP']['value'], 1) == 26.7 assert p.parsed['TMP']['raw_value'] == 85 assert p.learn is False
def test_eep_parsing(): status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x08, 0x28, 0x46, 0x80, 0x01, 0x8A, 0x7B, 0x30, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x49, 0x00, 0x26 ])) assert p.learn is True assert p.contains_eep is True assert p.rorg_func == 0x02 assert p.rorg_type == 0x05 assert p.status == 0x00 assert p.repeater_count == 0
def test_temperature(): ''' Tests RADIO message for EEP -profile 0xA5 0x02 0x05 ''' status, buf, p = Packet.parse_msg( bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x00, 0x00, 0x55, 0x08, 0x01, 0x81, 0xB7, 0x44, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x75 ])) assert p.parse_eep(0x02, 0x05) == ['TMP'] assert round(p.parsed['TMP']['value'], 1) == 26.7 assert p.parsed['TMP']['raw_value'] == 85 assert p.learn is False assert p.contains_eep is False assert p.rorg_func is None assert p.rorg_type is None
def test_eep_parsing(): status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x08, 0x28, 0x46, 0x80, 0x01, 0x8A, 0x7B, 0x30, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x49, 0x00, 0x26 ])) assert p.learn is True assert p.contains_eep is True assert p.rorg_func == 0x02 assert p.rorg_type == 0x05 assert round(p.parsed['TMP']['value'], 1) == 29.0 assert p.parsed['TMP']['raw_value'] == 70
def parse(self): ''' Parses messages and puts them to receive queue ''' # Loop while we get new messages while True: status, self._buffer, p = Packet.parse_msg(self._buffer) # If message is incomplete -> break the loop if status == PARSE_RESULT.INCOMPLETE: return status # If message is OK, add it to receive queue or send to the callback method if status == PARSE_RESULT.OK and p: if self.__callback is None: self.receive.put(p) else: self.__callback(p) logger.debug(p)
def parse(self): ''' Parses messages and puts them to receive queue ''' # Loop while we get new messages while True: status, self._buffer, packet = Packet.parse_msg(self._buffer, communicator=self) # If message is incomplete -> break the loop if status == PARSE_RESULT.INCOMPLETE: return status # If message is OK, add it to receive queue or send to the callback method if status == PARSE_RESULT.OK and packet: if self.__callback is None: self.receive.put(packet) else: self.__callback(packet) self.logger.debug(packet)
def test_packet_fails(): ''' Tests designed to fail. These include changes to checksum, data length or something like that. ''' fail_examples = ( bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x2B, 0xD2, 0xDD, 0xDC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x36 ]), bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x2B, 0xD2, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x37 ]), bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x1B, 0xD2, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x36 ]), bytearray([ 0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x38 ]), bytearray([ 0x55, 0x00, 0x01 ]), ) for msg in fail_examples: status, remainder, packet = Packet.parse_msg(msg) assert status in [PARSE_RESULT.INCOMPLETE, PARSE_RESULT.CRC_MISMATCH]
def test_temperature(): ''' Tests RADIO message for EEP -profile 0xA5 0x02 0x05 ''' status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x00, 0x00, 0x55, 0x08, 0x01, 0x81, 0xB7, 0x44, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x75 ])) assert p.parse_eep(0x02, 0x05) == ['TMP'] assert round(p.parsed['TMP']['value'], 1) == 26.7 assert p.parsed['TMP']['raw_value'] == 85 assert p.learn is False assert p.contains_eep is False assert p.rorg is 0xA5 assert p.rorg is int(RORG.BS4) assert p.rorg_func is 0x02 assert p.rorg_type is 0x05 assert p.status == 0x00 assert p.repeater_count == 0
def test_temperature(): ''' Tests RADIO message for EEP -profile 0xA5 0x02 0x05 ''' status, buf, packet = Packet.parse_msg( bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x00, 0x00, 0x55, 0x08, 0x01, 0x81, 0xB7, 0x44, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x2D, 0x00, 0x75 ])) assert packet.parse_eep(0x02, 0x05) == ['TMP'] assert round(packet.parsed['TMP']['value'], 1) == 26.7 assert packet.parsed['TMP']['raw_value'] == 85 assert packet.learn is False assert packet.contains_eep is False assert packet.rorg is 0xA5 assert packet.rorg is int(RORG.BS4) assert packet.rorg_func is 0x02 assert packet.rorg_type is 0x05 assert packet.status == 0x00 assert packet.repeater_count == 0 assert packet.sender == [0x01, 0x81, 0xB7, 0x44] assert packet.sender_hex == '01:81:B7:44'
def unpickle_packet(cls, text): unpickled = pickle.loads(codecs.decode(text.encode(), "base64")) packet_type = unpickled["packet_type"] data = unpickled["data"] opt_data = unpickled["optional"] # copied from: enocean/protocol/packet.py if packet_type == PACKET.RADIO_ERP1: # Need to handle UTE Teach-in here, as it's a separate packet type... if data[0] == RORG.UTE: packet = UTETeachInPacket(packet_type, data, opt_data) else: packet = RadioPacket(packet_type, data, opt_data) elif packet_type == PACKET.RESPONSE: packet = ResponsePacket(packet_type, data, opt_data) elif packet_type == PACKET.EVENT: packet = EventPacket(packet_type, data, opt_data) else: packet = Packet(packet_type, data, opt_data) return packet
def parse(self): ''' Parses messages and puts them to receive queue ''' # Loop while we get new messages while True: status, self._buffer, packet = Packet.parse_msg(self._buffer) # If message is incomplete -> break the loop if status == PARSE_RESULT.INCOMPLETE: return status # If message is OK, add it to receive queue or send to the callback method if status == PARSE_RESULT.OK and packet: packet.received = datetime.datetime.now() if isinstance(packet, UTETeachInPacket) and self.teach_in: response_packet = packet.create_response_packet(self.base_id) self.logger.info('Sending response to UTE teach-in.') self.send(response_packet) if self.__callback is None: self.receive.put(packet) else: self.__callback(packet) self.logger.debug(packet)
def test_packet_examples(): ''' Tests examples found at EnOceanSerialProtocol3.pdf / 74 ''' telegram_examples = { # Radio VLD PACKET.RADIO: { 'msg': bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x2B, 0xD2, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x36]), 'data_len': 15, 'opt_len': 7 }, # CO_WR_SLEEP PACKET.COMMON_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x05, 0x00, 0x05, 0xDB, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x54]), 'data_len': 5, 'opt_len': 0 }, # CO_WR_RESET PACKET.COMMON_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x02, 0x0E]), 'data_len': 1, 'opt_len': 0 }, # CO_RD_IDBASE PACKET.COMMON_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x08, 0x38]), 'data_len': 1, 'opt_len': 0, }, # Response RET_OK PACKET.RESPONSE: { 'msg': bytearray([ 0x55, 0x00, 0x05, 0x00, 0x02, 0xCE, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xDA]), 'data_len': 5, 'opt_len': 0 }, # REMOTE_MAN_COMMAND PACKET.REMOTE_MAN_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x19, 0x00, 0x07, 0x8D, 0x12, 0x12, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xDA]), 'data_len': 25, 'opt_len': 0 }, # QueryID PACKET.REMOTE_MAN_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x0C, 0x00, 0x07, 0xEF, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x65]), 'data_len': 12, 'opt_len': 0 }, # Custom test, containing 0x55 in message PACKET.RESPONSE: { 'msg': bytearray([ 0x55, 0x00, 0x05, 0x01, 0x02, 0xDB, 0x00, 0xFF, 0x9E, 0x55, 0x00, 0x0A, 0x79, # un necessary data, to check for message length checking 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]), 'data_len': 5, 'opt_len': 1 } } for packet, values in telegram_examples.items(): status, remainder, p = Packet.parse_msg(values['msg']) assert status == PARSE_RESULT.OK assert p.type != 0x00 assert p.type == packet assert len(p.data) == values['data_len'] assert len(p.optional) == values['opt_len']
def test_vld(): status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x09, 0x07, 0x01, 0x56, 0xD2, 0x04, 0x00, 0x64, 0x01, 0x94, 0xE3, 0xB9, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0xE4 ])) assert p.rorg == RORG.VLD assert p.parse_eep(0x01, 0x01) == ['PF', 'PFD', 'CMD', 'OC', 'EL', 'IO', 'LC', 'OV'] assert p.parsed['EL']['raw_value'] == 0 assert p.parsed['EL']['value'] == 'Error level 0: hardware OK' assert p.parsed['PF']['raw_value'] == 0 assert p.parsed['PF']['value'] == 'Power Failure Detection disabled/not supported' assert p.parsed['PFD']['raw_value'] == 0 assert p.parsed['PFD']['value'] == 'Power Failure Detection not detected/not supported/disabled' assert p.parsed['IO']['raw_value'] == 0 assert p.parsed['IO']['value'] == 'Output channel 0 (to load)' assert p.parsed['OV']['raw_value'] == 100 assert p.parsed['OV']['value'] == 'Output value 100% or ON' assert p.parsed['OC']['raw_value'] == 0 assert p.parsed['OC']['value'] == 'Over current switch off: ready / not supported' assert p.parsed['LC']['raw_value'] == 0 assert p.parsed['LC']['value'] == 'Local control disabled / not supported' status, buf, p = Packet.parse_msg(bytearray([ 0x55, 0x00, 0x09, 0x07, 0x01, 0x56, 0xD2, 0x04, 0x00, 0x00, 0x01, 0x94, 0xE3, 0xB9, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0xBF ])) assert p.rorg == RORG.VLD assert p.parse_eep(0x01, 0x01) == ['PF', 'PFD', 'CMD', 'OC', 'EL', 'IO', 'LC', 'OV'] assert p.parsed['EL']['raw_value'] == 0 assert p.parsed['EL']['value'] == 'Error level 0: hardware OK' assert p.parsed['PF']['raw_value'] == 0 assert p.parsed['PF']['value'] == 'Power Failure Detection disabled/not supported' assert p.parsed['PFD']['raw_value'] == 0 assert p.parsed['PFD']['value'] == 'Power Failure Detection not detected/not supported/disabled' assert p.parsed['IO']['raw_value'] == 0 assert p.parsed['IO']['value'] == 'Output channel 0 (to load)' assert p.parsed['OV']['raw_value'] == 0 assert p.parsed['OV']['value'] == 'Output value 0% or OFF' assert p.parsed['OC']['raw_value'] == 0 assert p.parsed['OC']['value'] == 'Over current switch off: ready / not supported' assert p.parsed['LC']['raw_value'] == 0 assert p.parsed['LC']['value'] == 'Local control disabled / not supported'
def assemble_radio_packet(transmitter_id): return RadioPacket.create(rorg=RORG.BS4, func=0x20, type=0x01, sender=transmitter_id, CV=50, TMP=21.5, ES='true') init_logging() c = SerialCommunicator() c.start() # Request transmitter ID p = Packet(PACKET.COMMON_COMMAND, [0x08]) c.send(p) # Fetch the transmitter ID for sending packages. # NOT TESTED!!! # Needs testing, and if functional, a similar loop should be implemented to the communicator initialization. # This ID would then be used to send all future messages. transmitter_id = None while transmitter_id is None: try: p = c.receive.get(block=True, timeout=1) if p.type == PACKET.RESPONSE: transmitter_id = p.response_data # send custom radio packet c.send(assemble_radio_packet(transmitter_id)) break
def test_packet_examples(): ''' Tests examples found at EnOceanSerialProtocol3.pdf / 74 ''' telegram_examples = { # Radio VLD PACKET.RADIO: { 'msg': bytearray([ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x2B, 0xD2, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x36 ]), 'data_len': 15, 'opt_len': 7, }, # CO_WR_SLEEP PACKET.COMMON_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x05, 0x00, 0x05, 0xDB, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x54 ]), 'data_len': 5, 'opt_len': 0, }, # CO_WR_RESET PACKET.COMMON_COMMAND: { 'msg': bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x02, 0x0E]), 'data_len': 1, 'opt_len': 0, }, # CO_RD_IDBASE PACKET.COMMON_COMMAND: { 'msg': bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x08, 0x38]), 'data_len': 1, 'opt_len': 0, }, # Response RET_OK PACKET.RESPONSE: { 'msg': bytearray([ 0x55, 0x00, 0x05, 0x00, 0x02, 0xCE, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xDA ]), 'data_len': 5, 'opt_len': 0, }, # REMOTE_MAN_COMMAND PACKET.REMOTE_MAN_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x19, 0x00, 0x07, 0x8D, 0x12, 0x12, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xDA ]), 'data_len': 25, 'opt_len': 0, }, # QueryID PACKET.REMOTE_MAN_COMMAND: { 'msg': bytearray([ 0x55, 0x00, 0x0C, 0x00, 0x07, 0xEF, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x65 ]), 'data_len': 12, 'opt_len': 0, }, # Custom test, containing 0x55 in message PACKET.RESPONSE: { 'msg': bytearray([ 0x55, 0x00, 0x05, 0x01, 0x02, 0xDB, 0x00, 0xFF, 0x9E, 0x55, 0x00, 0x0A, 0x79, # unnecessary data, to check for message length checking 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]), 'data_len': 5, 'opt_len': 1, } } for packet, values in telegram_examples.items(): status, remainder, p = Packet.parse_msg(values['msg']) assert status == PARSE_RESULT.OK assert p.type != 0x00 assert p.type == packet assert len(p.data) == values['data_len'] assert len(p.optional) == values['opt_len'] assert p.status == 0x00 assert p.repeater_count == 0
def test_packet_examples(): """ Tests examples found at EnOceanSerialProtocol3.pdf / 74 """ telegram_examples = { # Radio VLD PACKET.RADIO: { "msg": bytearray( [ 0x55, 0x00, 0x0F, 0x07, 0x01, 0x2B, 0xD2, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x80, 0x35, 0xC4, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 0x00, 0x36, ] ), "data_len": 15, "opt_len": 7, }, # CO_WR_SLEEP PACKET.COMMON_COMMAND: { "msg": bytearray([0x55, 0x00, 0x05, 0x00, 0x05, 0xDB, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x54]), "data_len": 5, "opt_len": 0, }, # CO_WR_RESET PACKET.COMMON_COMMAND: { "msg": bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x02, 0x0E]), "data_len": 1, "opt_len": 0, }, # CO_RD_IDBASE PACKET.COMMON_COMMAND: { "msg": bytearray([0x55, 0x00, 0x01, 0x00, 0x05, 0x70, 0x08, 0x38]), "data_len": 1, "opt_len": 0, }, # Response RET_OK PACKET.RESPONSE: { "msg": bytearray([0x55, 0x00, 0x05, 0x00, 0x02, 0xCE, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xDA]), "data_len": 5, "opt_len": 0, }, # REMOTE_MAN_COMMAND PACKET.REMOTE_MAN_COMMAND: { "msg": bytearray( [ 0x55, 0x00, 0x19, 0x00, 0x07, 0x8D, 0x12, 0x12, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0xDA, ] ), "data_len": 25, "opt_len": 0, }, # QueryID PACKET.REMOTE_MAN_COMMAND: { "msg": bytearray( [ 0x55, 0x00, 0x0C, 0x00, 0x07, 0xEF, 0x00, 0x04, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x65, ] ), "data_len": 12, "opt_len": 0, }, # Custom test, containing 0x55 in message PACKET.RESPONSE: { "msg": bytearray( [ 0x55, 0x00, 0x05, 0x01, 0x02, 0xDB, 0x00, 0xFF, 0x9E, 0x55, 0x00, 0x0A, 0x79, # unnecessary data, to check for message length checking 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ] ), "data_len": 5, "opt_len": 1, }, } for packet, values in telegram_examples.items(): status, remainder, pack = Packet.parse_msg(values["msg"]) assert status == PARSE_RESULT.OK assert pack.packet_type != 0x00 assert pack.packet_type == packet assert len(pack.data) == values["data_len"] assert len(pack.optional) == values["opt_len"] assert pack.status == 0x00 assert pack.repeater_count == 0
def send_command(self, packet_type, data, optional): """Send a command via the EnOcean dongle.""" packet = Packet(packet_type, data=data, optional=optional) self.hass.helpers.dispatcher.dispatcher_send(SIGNAL_SEND_PACKET, packet)
import traceback import sys try: import queue except ImportError: import Queue as queue init_logging() """ '/dev/ttyUSB0' might change depending on where your device is. To prevent running the app as root, change the access permissions: 'sudo chmod 777 /dev/ttyUSB0' """ communicator = SerialCommunicator(port=u'/dev/ttyUSB0', callback=None) packet = Packet(PACKET.COMMON_COMMAND, [0x03]) communicator.daemon = True communicator.start() communicator.send(packet) while communicator.is_alive(): try: receivedPacket = communicator.receive.get(block=True, timeout=1) if receivedPacket.packet_type == PACKET.RESPONSE: print('Return Code: %s' % utils.to_hex_string(receivedPacket.data[0])) print('APP version: %s' % utils.to_hex_string(receivedPacket.data[1:5])) print('API version: %s' % utils.to_hex_string(receivedPacket.data[5:9]))
def test_packet_assembly(): PACKET_CONTENT_1 = bytearray([ 0x55, 0x00, 0x0A, 0x00, 0x01, 0x80, 0xA5, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x18 ]) PACKET_CONTENT_2 = bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xE4 ]) PACKET_CONTENT_3 = bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x32, 0x20, 0x89, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x43 ]) PACKET_CONTENT_4 = bytearray([ 0x55, 0x00, 0x0A, 0x07, 0x01, 0xEB, 0xA5, 0x32, 0x00, 0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80 ]) # manually assemble packet packet = Packet(PACKET.RADIO_ERP1) packet.rorg = RORG.BS4 sender_bytes = [(0xdeadbeef >> i & 0xff) for i in (24, 16, 8, 0)] data = [0, 0, 0, 0] packet.data = [packet.rorg] + data + sender_bytes + [0] # test content packet_serialized = packet.build() assert len(packet_serialized) == len(PACKET_CONTENT_1) assert list(packet_serialized) == list(PACKET_CONTENT_1) # set optional data sub_tel_num = 3 destination = [255, 255, 255, 255] # broadcast dbm = 0xff security = 0 packet.optional = [sub_tel_num] + destination + [dbm] + [security] # test content packet_serialized = packet.build() assert len(packet_serialized) == len(PACKET_CONTENT_2) assert list(packet_serialized) == list(PACKET_CONTENT_2) # update data based on EEP packet.select_eep(0x20, 0x01, 1) prop = { 'CV': 50, 'TMP': 21.5, 'ES': 'true', } packet.set_eep(prop) # test content packet_serialized = packet.build() assert len(packet_serialized) == len(PACKET_CONTENT_3) assert list(packet_serialized) == list(PACKET_CONTENT_3) assert packet.rorg_func == 0x20 assert packet.rorg_type == 0x01 # Test the easier method of sending packets. packet = Packet.create(PACKET.RADIO_ERP1, rorg=RORG.BS4, rorg_func=0x20, rorg_type=0x01, learn=True, direction=1, **prop) packet_serialized = packet.build() assert len(packet_serialized) == len(PACKET_CONTENT_3) assert list(packet_serialized) == list(PACKET_CONTENT_3) assert packet.rorg_func == 0x20 assert packet.rorg_type == 0x01 # Test creating RadioPacket directly. packet = RadioPacket.create(rorg=RORG.BS4, rorg_func=0x20, rorg_type=0x01, learn=True, direction=2, SP=50) packet_serialized = packet.build() assert len(packet_serialized) == len(PACKET_CONTENT_4) assert list(packet_serialized) == list(PACKET_CONTENT_4) assert packet.rorg_func == 0x20 assert packet.rorg_type == 0x01
def send_command(self, data, optional, packet_type): """Send a command via the EnOcean dongle.""" packet = Packet(packet_type, data=data, optional=optional) self.opp.helpers.dispatcher.dispatcher_send(SIGNAL_SEND_MESSAGE, packet)
def send_command(self, data, optional, packet_type): """Send a command via the EnOcean dongle.""" from enocean.protocol.packet import Packet packet = Packet(packet_type, data=data, optional=optional) ENOCEAN_DONGLE.send_command(packet)