private byte[] waitForResponse(final IndividualAddress from, final int minAsduLen,
		final int maxAsduLen, final long timeout) throws KNXInvalidResponseException,
		KNXTimeoutException, InterruptedException
	{
		long remaining = timeout;
		final long end = System.currentTimeMillis() + remaining;
		synchronized (indications) {
			while (remaining > 0) {
				while (indications.size() > 0) {
					final CEMI frame = ((FrameEvent) indications.remove(0)).getFrame();
					final byte[] apdu = frame.getPayload();
					if (svcResponse != DataUnitBuilder.getAPDUService(apdu))
						continue;
					// broadcasts set parameter from to null; we then accept every sender address
					if (from != null) {
						if (!((CEMILData) frame).getSource().equals(from))
							continue;
					}
					if (apdu.length < minAsduLen + 2 || apdu.length > maxAsduLen + 2) {
						final String s = "invalid ASDU response length " + (apdu.length - 2)
								+ " bytes, expected " + minAsduLen + " to " + maxAsduLen;
						logger.error("received response with " + s);
						throw new KNXInvalidResponseException(s);
					}
					if (svcResponse == IND_ADDR_RESPONSE || svcResponse == IND_ADDR_SN_RESPONSE)
						return ((CEMILData) frame).getSource().toByteArray();
					indications.clear();
					return apdu;
				}
				indications.wait(remaining);
				remaining = end - System.currentTimeMillis();
			}
		}
		throw new KNXTimeoutException("timeout occurred while waiting for data response");
	}