def up_down_by_arrival(*filters, local_dir=".",
                       remote_dir=DEFAULT_REMOTE_DIR):
    """Monitors a local directory and a remote FlashAir directory and
    generates sets of new files to be uploaded or downloaded.
    Sets to upload are generated in a tuple
    like (Direction.up, {...}), while download sets to download
    are generated in a tuple like (Direction.down, {...}). The generator yields
    before each upload or download actually takes place."""
    local_monitor = watch_local_files(*filters, local_dir=local_dir)
    remote_monitor = watch_remote_files(*filters, remote_dir=remote_dir)
    _, lfile_set = next(local_monitor)
    _, rfile_set = next(remote_monitor)
    _notify_sync_ready(len(lfile_set), local_dir, remote_dir)
    _notify_sync_ready(len(rfile_set), remote_dir, local_dir)
    processed = set()
    for new_local, new_remote in zip(local_monitor, remote_monitor):
        new_local, local_set = new_local
        local_arrivals = {f for f in new_local if f.filename not in processed}
        yield Direction.up, local_arrivals
        if local_arrivals:
            new_names.update(f.filename for f in local_arrivals)
            _notify_sync(Direction.up, local_arrivals)
            up_by_files(local_arrivals, remote_dir)
            _notify_sync_ready(len(local_set), local_dir, remote_dir)
        new_remote, remote_set = new_remote
        remote_arrivals = {f for f in new_remote if f.filename not in processed}
        yield Direction.down, remote_arrivals
        if remote_arrivals:
            new_names.update(f.filename for f in remote_arrivals)
            _notify_sync(Direction.down, remote_arrivals)
            yield Direction.down, remote_arrivals
            down_by_files(remote_arrivals, local_dir)
            _notify_sync_ready(len(remote_set), remote_dir, local_dir)