def _connect_mv_node(network, node, target_obj):
    """Connects MV node to target object in MV grid

    If the target object is a node, a new line is created to it.
    If the target object is a line, the node is connected to a newly created branch tee
    (using perpendicular projection) on this line.
    New lines are created using standard equipment.

    Parameters
    ----------
    network : :class:`~.grid.network.Network`
        The eDisGo container object
    node : :class:`~.grid.components.Component`
        Node to connect (e.g. :class:`~.grid.components.Generator`)
        Node must be a member of MV grid's graph (network.mv_grid.graph)
    target_obj : :class:`~.grid.components.Component`
        Object that node shall be connected to

    Returns
    -------
    :class:`~.grid.components.Component` or None
        Node that node was connected to

    Notes
    -----
    Adapted from `Ding0 <https://github.com/openego/ding0/blob/\
        21a52048f84ec341fe54e0204ac62228a9e8a32a/\
        ding0/grid/mv_grid/mv_connect.py#L311>`_.
    """

    # get standard equipment
    std_line_type = network.equipment_data['mv_cables'].loc[
        network.config['grid_expansion_standard_equipment']['mv_line']]
    std_line_kind = 'cable'

    target_obj_result = None

    node_shp = transform(proj2equidistant(network), node.geom)

    # MV line is nearest connection point
    if isinstance(target_obj['shp'], LineString):

        adj_node1 = target_obj['obj']['adj_nodes'][0]
        adj_node2 = target_obj['obj']['adj_nodes'][1]

        # find nearest point on MV line
        conn_point_shp = target_obj['shp'].interpolate(target_obj['shp'].project(node_shp))
        conn_point_shp = transform(proj2conformal(network), conn_point_shp)

        line = network.mv_grid.graph.edge[adj_node1][adj_node2]

        # target MV line does currently not connect a load area of type aggregated
        if not line['type'] == 'line_aggr':

            # create branch tee and add it to grid
            branch_tee = BranchTee(geom=conn_point_shp,
                                   grid=network.mv_grid,
                                   in_building=False)
            network.mv_grid.graph.add_node(branch_tee,
                                           type='branch_tee')

            # split old branch into 2 segments
            # (delete old branch and create 2 new ones along cable_dist)
            # ==========================================================

            # backup kind and type of branch
            line_kind = line['line'].kind
            line_type = line['line'].type

            # remove line from graph
            network.mv_grid.graph.remove_edge(adj_node1, adj_node2)

            # delete line from equipment changes if existing
            _del_cable_from_equipment_changes(network=network,
                                              line=line['line'])

            line_length = calc_geo_dist_vincenty(network=network,
                                                 node_source=adj_node1,
                                                 node_target=branch_tee)
            line = Line(id=random.randint(10 ** 8, 10 ** 9),
                        length=line_length / 1e3,
                        quantity=1,
                        kind=line_kind,
                        type=line_type,
                        grid=network.mv_grid)

            network.mv_grid.graph.add_edge(adj_node1,
                                           branch_tee,
                                           line=line,
                                           type='line')

            # add line to equipment changes to track costs
            _add_cable_to_equipment_changes(network=network,
                                            line=line)

            line_length = calc_geo_dist_vincenty(network=network,
                                                 node_source=adj_node2,
                                                 node_target=branch_tee)
            line = Line(id=random.randint(10 ** 8, 10 ** 9),
                        length=line_length / 1e3,
                        quantity=1,
                        kind=line_kind,
                        type=line_type,
                        grid=network.mv_grid)

            network.mv_grid.graph.add_edge(adj_node2,
                                           branch_tee,
                                           line=line,
                                           type='line')

            # add line to equipment changes to track costs
            _add_cable_to_equipment_changes(network=network,
                                            line=line)

            # add new branch for new node (node to branch tee)
            # ================================================
            line_length = calc_geo_dist_vincenty(network=network,
                                                 node_source=node,
                                                 node_target=branch_tee)
            line = Line(id=random.randint(10 ** 8, 10 ** 9),
                        length=line_length / 1e3,
                        quantity=1,
                        kind=std_line_kind,
                        type=std_line_type,
                        grid=network.mv_grid)

            network.mv_grid.graph.add_edge(node,
                                           branch_tee,
                                           line=line,
                                           type='line')

            # add line to equipment changes to track costs
            _add_cable_to_equipment_changes(network=network,
                                            line=line)

            target_obj_result = branch_tee

    # node ist nearest connection point
    else:

        # what kind of node is to be connected? (which type is node of?)
        #   LVStation: Connect to LVStation or BranchTee
        #   Generator: Connect to LVStation, BranchTee or Generator
        if isinstance(node, LVStation):
            valid_conn_objects = (LVStation, BranchTee)
        elif isinstance(node, Generator):
            valid_conn_objects = (LVStation, BranchTee, Generator)
        else:
            raise ValueError('Oops, the node you are trying to connect is not a valid connection object')

        # if target is generator or Load, check if it is aggregated (=> connection not allowed)
        if isinstance(target_obj['obj'], (Generator, Load)):
            target_is_aggregated = any([_ for _ in network.mv_grid.graph.edge[target_obj['obj']].values()
                                        if _['type'] == 'line_aggr'])
        else:
            target_is_aggregated = False

        # target node is not a load area of type aggregated
        if isinstance(target_obj['obj'], valid_conn_objects) and not target_is_aggregated:

            # add new branch for satellite (station to station)
            line_length = calc_geo_dist_vincenty(network=network,
                                                 node_source=node,
                                                 node_target=target_obj['obj'])

            line = Line(id=random.randint(10 ** 8, 10 ** 9),
                        type=std_line_type,
                        kind=std_line_kind,
                        quantity=1,
                        length=line_length / 1e3,
                        grid=network.mv_grid)

            network.mv_grid.graph.add_edge(node,
                                           target_obj['obj'],
                                           line=line,
                                           type='line')

            # add line to equipment changes to track costs
            _add_cable_to_equipment_changes(network=network,
                                            line=line)

            target_obj_result = target_obj['obj']

    return target_obj_result