Start sending a message at a given period on this bus.

        The task will be active until one of the following conditions are met:

        - the (optional) duration expires
        - the Bus instance goes out of scope
        - the Bus instance is shutdown
        - :meth:`BusABC.stop_all_periodic_tasks()` is called
        - the task's :meth:`CyclicTask.stop()` method is called.

        :param can.Message msg:
            Message to transmit
        :param float period:
            Period in seconds between each message
        :param float duration:
            The duration to keep sending this message at given rate. If
            no duration is provided, the task will continue indefinitely.
        :param bool store_task:
            If True (the default) the task will be attached to this Bus instance.
            Disable to instead manage tasks manually.
        :return:
            A started task instance. Note the task can be stopped (and depending on
            the backend modified) by calling the :meth:`stop` method.
        :rtype: can.broadcastmanager.CyclicSendTaskABC

        .. note::

            Note the duration before the message stops being sent may not
            be exactly the same as the duration specified by the user. In
            general the message will be sent at the given rate until at
            least **duration** seconds.

        .. note::

            For extremely long running Bus instances with many short lived tasks the default
            api with ``store_task==True`` may not be appropriate as the stopped tasks are
            still taking up memory as they are associated with the Bus instance.

def send_periodic(self, msg, period, duration=None, store_task=True):
        """Start sending a message at a given period on this bus.

        The task will be active until one of the following conditions are met:

        - the (optional) duration expires
        - the Bus instance goes out of scope
        - the Bus instance is shutdown
        - :meth:`BusABC.stop_all_periodic_tasks()` is called
        - the task's :meth:`CyclicTask.stop()` method is called.

        :param can.Message msg:
            Message to transmit
        :param float period:
            Period in seconds between each message
        :param float duration:
            The duration to keep sending this message at given rate. If
            no duration is provided, the task will continue indefinitely.
        :param bool store_task:
            If True (the default) the task will be attached to this Bus instance.
            Disable to instead manage tasks manually.
        :return:
            A started task instance. Note the task can be stopped (and depending on
            the backend modified) by calling the :meth:`stop` method.
        :rtype: can.broadcastmanager.CyclicSendTaskABC

        .. note::

            Note the duration before the message stops being sent may not
            be exactly the same as the duration specified by the user. In
            general the message will be sent at the given rate until at
            least **duration** seconds.

        .. note::

            For extremely long running Bus instances with many short lived tasks the default
            api with ``store_task==True`` may not be appropriate as the stopped tasks are
            still taking up memory as they are associated with the Bus instance.
        """
        task = self._send_periodic_internal(msg, period, duration)
        # we wrap the task's stop method to also remove it from the Bus's list of tasks
        original_stop_method = task.stop

        def wrapped_stop_method(remove_task=True):
            if remove_task:
                try:
                    self._periodic_tasks.remove(task)
                except ValueError:
                    pass
            original_stop_method()
        task.stop = wrapped_stop_method

        if store_task:
            self._periodic_tasks.append(task)

        return task