def frame_received(self, data): """Handle a received EZSP frame The protocol has taken care of UART specific framing etc, so we should just have EZSP application stuff here, with all escaping/stuffing and data randomization removed. """ sequence, frame_id, data = data[0], data[2], data[3:] if frame_id == 0xFF: frame_id = 0 if len(data) > 1: frame_id = data[1] data = data[2:] frame_name = self.COMMANDS_BY_ID[frame_id][0] LOGGER.debug( "Application frame %s (%s) received", frame_id, frame_name, ) if sequence in self._awaiting: expected_id, schema, future = self._awaiting.pop(sequence) assert expected_id == frame_id result, data = t.deserialize(data, schema) future.set_result(result) else: schema = self.COMMANDS_BY_ID[frame_id][2] frame_name = self.COMMANDS_BY_ID[frame_id][0] result, data = t.deserialize(data, schema) self.handle_callback(frame_name, result) if frame_id == 0x00: self.ezsp_version = result[0]
def frame_received(self, data): """Handle a received EZSP frame The protocol has taken care of UART specific framing etc, so we should just have EZSP application stuff here, with all escaping/stuffing and data randomization removed. """ sequence, frame_id, data = data[0], data[2], data[3:] if frame_id == 0xFF: frame_id = 0 if len(data) > 1: frame_id = data[1] data = data[2:] frame_name = self.COMMANDS_BY_ID[frame_id][0] LOGGER.debug( "Application frame %s (%s) received: %s", frame_id, frame_name, binascii.hexlify(data), ) if sequence in self._awaiting: expected_id, schema, future = self._awaiting.pop(sequence) assert expected_id == frame_id result, data = t.deserialize(data, schema) try: future.set_result(result) except asyncio.InvalidStateError: LOGGER.debug( "Error processing %s response. %s command timed out?", sequence, self.COMMANDS_BY_ID.get(expected_id, [expected_id])[0], ) else: schema = self.COMMANDS_BY_ID[frame_id][2] frame_name = self.COMMANDS_BY_ID[frame_id][0] result, data = t.deserialize(data, schema) self.handle_callback(frame_name, result)
def deserialize(aps_frame, data): frame_control, data = data[0], data[1:] frame_type = frame_control & 0b0011 direction = (frame_control & 0b1000) >> 3 if frame_control & 0b0100: # Manufacturer specific value present data = data[2:] tsn, command_id, data = data[0], data[1], data[2:] is_reply = bool(direction) if frame_type == 1: # Cluster command if aps_frame.clusterId not in Cluster._registry: LOGGER.debug("Ignoring unknown cluster ID 0x%04x", aps_frame.clusterId) return tsn, command_id + 256, is_reply, data cluster = Cluster._registry[aps_frame.clusterId] # Cluster-specific command if direction: commands = cluster.client_commands else: commands = cluster.server_commands try: schema = commands[command_id][1] is_reply = commands[command_id][2] except KeyError: LOGGER.warning("Unknown cluster-specific command %s", command_id) return tsn, command_id + 256, is_reply, data # Bad hack to differentiate foundation vs cluster command_id = command_id + 256 else: # General command try: schema = foundation.COMMANDS[command_id][1] is_reply = foundation.COMMANDS[command_id][2] except KeyError: LOGGER.warning("Unknown foundation command %s", command_id) return tsn, command_id, is_reply, data value, data = t.deserialize(data, schema) if data != b'': # TODO: Seems sane to check, but what should we do? LOGGER.warning("Data remains after deserializing ZCL frame") return tsn, command_id, is_reply, value
def deserialize(cluster_id, data): tsn, data = data[0], data[1:] is_reply = bool(cluster_id & 0x8000) try: cluster_details = types.CLUSTERS[cluster_id] except KeyError: LOGGER.warning("Unknown ZDO cluster 0x%02x", cluster_id) return tsn, cluster_id, is_reply, data args, data = t.deserialize(data, cluster_details[2]) if data != b'': # TODO: Seems sane to check, but what should we do? LOGGER.warning("Data remains after deserializing ZDO frame") return tsn, cluster_id, is_reply, args