def wait(self, condition_or_value, timeout=None):
        """Wait for the sensor to satisfy a condition.

        Parameters
        ----------
        condition_or_value : obj or callable, or seq of objs or callables
            If obj, sensor.value is compared with obj. If callable,
            condition_or_value(reading) is called, and must return True if its
            condition is satisfied. Since the reading is passed in, the value,
            status, timestamp or received_timestamp attributes can all be used
            in the check.
            TODO: Sequences of conditions (use SensorTransitionWaiter thingum?)
        timeout : float or None
            The timeout in seconds (None means wait forever)

        Returns
        -------
        This command returns a tornado Future that resolves with True when the
        sensor value satisfies the condition. It will never resolve with False;
        if a timeout is given a TimeoutError happens instead.

        Raises
        ------
        :class:`KATCPSensorError`
            If the sensor does not have a strategy set
        :class:`tornado.gen.TimeoutError`
            If the sensor condition still fails after a stated timeout period

        """
        if (isinstance(condition_or_value, collections.Sequence) and not
                isinstance(condition_or_value, basestring)):
            raise NotImplementedError(
                'Currently only single conditions are supported')
        condition_test = (condition_or_value if callable(condition_or_value)
                          else lambda s: s.value == condition_or_value)

        ioloop = tornado.ioloop.IOLoop.current()
        f = Future()
        if self.sampling_strategy == ('none', ):
            raise KATCPSensorError(
                'Cannot wait on a sensor that does not have a strategy set')

        def handle_update(sensor, reading):
            # This handler is called whenever a sensor update is received
            try:
                assert sensor is self
                if condition_test(reading):
                    self.unregister_listener(handle_update)
                    # Try and be idempotent if called multiple times after the
                    # condition is matched. This should not happen unless the
                    # sensor object is being updated in a thread outside of the
                    # ioloop.
                    if not f.done():
                        ioloop.add_callback(f.set_result, True)
            except Exception:
                f.set_exc_info(sys.exc_info())
                self.unregister_listener(handle_update)

        self.register_listener(handle_update, reading=True)
        # Handle case where sensor is already at the desired value
        ioloop.add_callback(handle_update, self, self._reading)

        if timeout:
            to = ioloop.time() + timeout
            timeout_f = with_timeout(to, f)
            # Make sure we stop listening if the wait times out to prevent a
            # buildup of listeners
            timeout_f.add_done_callback(
                lambda f: self.unregister_listener(handle_update))
            return timeout_f
        else:
            return f
Wait for the sensor to satisfy a condition.

        Parameters
        ----------
        condition_or_value : obj or callable, or seq of objs or callables
            If obj, sensor.value is compared with obj. If callable,
            condition_or_value(reading) is called, and must return True if its
            condition is satisfied. Since the reading is passed in, the value,
            status, timestamp or received_timestamp attributes can all be used
            in the check.
            TODO: Sequences of conditions (use SensorTransitionWaiter thingum?)
        timeout : float or None
            The timeout in seconds (None means wait forever)

        Returns
        -------
        This command returns a tornado Future that resolves with True when the
        sensor value satisfies the condition. It will never resolve with False;
        if a timeout is given a TimeoutError happens instead.

        Raises
        ------
        :class:`KATCPSensorError`
            If the sensor does not have a strategy set
        :class:`tornado.gen.TimeoutError`
            If the sensor condition still fails after a stated timeout period