async def METHOD_NAME(
    self,
    node_id: NodeId,
    hex_processor: HexRecordProcessor,
    ack_wait_seconds: float,
) -> AsyncIterator[float]:
    """Download hex record chunks to node.
    Args:
        node_id: The target node id.
        hex_processor: The producer of hex chunks.
        ack_wait_seconds: Number of seconds to wait for an ACK.
    Returns:
        None
    """
    chunks = list(hex_processor.process(fields.FirmwareUpdateDataField.NUM_BYTES))
    total_chunks = len(chunks)
    with WaitableCallback(self._messenger) as reader:
        num_messages = 0
        crc32 = 0
        for chunk in chunks:
            logger.debug(
                f"Sending chunk {num_messages} to address {chunk.address:x}."
            )
            # Create and send message from this chunk
            data = bytes(chunk.data)
            data_message = message_definitions.FirmwareUpdateData(
                payload=payloads.FirmwareUpdateData.create(
                    address=chunk.address, data=data
                )
            )
            await self._messenger.send(node_id=node_id, message=data_message)
            try:
                # Wait for ack.
                await asyncio.wait_for(
                    self._wait_data_message_ack(node_id, reader), ack_wait_seconds
                )
            except asyncio.TimeoutError:
                raise TimeoutResponse(data_message, node_id)
            crc32 = binascii.crc32(data, crc32)
            num_messages += 1
            yield num_messages / total_chunks
        # Create and send firmware update complete message.
        complete_message = message_definitions.FirmwareUpdateComplete(
            payload=payloads.FirmwareUpdateComplete(
                num_messages=UInt32Field(num_messages), crc32=UInt32Field(crc32)
            )
        )
        await self._messenger.send(node_id=node_id, message=complete_message)
        try:
            # wait for ack.
            await asyncio.wait_for(
                self._wait_update_complete_ack(node_id, reader), ack_wait_seconds
            )
        except asyncio.TimeoutError:
            raise TimeoutResponse(complete_message, node_id)