示例#1
1
文件: tests.py 项目: Zearin/pyee
def test_emit_return():
    ee = EventEmitter()
    
    # make sure emission without callback retruns False
    nt.assert_false(ee.emit('data'))

    # add a callback
    ee.on('data')(lambda: None)

    # should return true now
    nt.assert_true(ee.emit('data'))
class DummyEmitter(object):
    """Dummy emitter for testing."""

    __emitter = None

    def __init__(self):
        """ctor."""
        self.__emitter = EventEmitter()

    def on(self, evt, callback):
        """Register event handler."""
        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Fire event."""
        self.__emitter.emit(evt, args)

    def on_pin_state_change(self, psce):
        """Fire the pin state change event."""
        self.emit("gpioStateChanged", psce)

    def trigger_event(self):
        """Trigger the state change event."""
        pin_address = gpio_pins.Gpio01.value
        old_state = pin_state.LOW
        new_state = pin_state.HIGH
        evt = PinStateChangeEvent(old_state, new_state, pin_address)
        self.on_pin_state_change(evt)
示例#3
0
def test_listener_removal():
    """Removing listeners removes the correct listener from an event."""

    ee = EventEmitter()

    # Some functions to pass to the EE
    def first():
        return 1

    ee.on('event', first)

    @ee.on('event')
    def second():
        return 2

    @ee.on('event')
    def third():
        return 3

    def fourth():
        return 4

    ee.on('event', fourth)

    assert ee._events['event'] == [first, second, third, fourth]

    ee.remove_listener('event', second)

    assert ee._events['event'] == [first, third, fourth]

    ee.remove_listener('event', first)
    assert ee._events['event'] == [third, fourth]

    ee.remove_all_listeners('event')
    assert ee._events['event'] == []
示例#4
0
class DummyEmitter(object):
    """Dummy emitter for testing."""

    __emitter = None
    __evt = None
    __pollThread = None

    def __init__(self):
        """ctor."""
        self.__emitter = EventEmitter()

    def on(self, evt, callback):
        """Register event handler."""
        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Fire event."""
        self.__emitter.emit(evt, args)

    def on_poll_fail(self):
        """Fire pin poll faiure event."""
        self.emit("pinPollFailed", self.__evt)

    def poll(self):
        """Execute pin polling on background thread."""
        ioEx = IOException("Poll failed.")
        self.__evt = PinPollFailEvent(ioEx)
        self.__pollThread = threading.Thread(target=self.on_poll_fail)
        self.__pollThread.name = "DummyEmitterThread"
        self.__pollThread.daemon = True
        self.__pollThread.start()
示例#5
0
class InterceptEmitter(object):
    """
    This class intercepts and allows emitting events between the
    skill_tester and the skill being tested.
    When a test is running emitted communication is intercepted for analysis
    """

    def __init__(self):
        self.emitter = EventEmitter()
        self.q = None

    def on(self, event, f):
        # run all events
        print("Event: ", event)
        self.emitter.on(event, f)

    def emit(self, event, *args, **kwargs):
        event_name = event.type
        if self.q:
            self.q.put(event)
        self.emitter.emit(event_name, event, *args, **kwargs)

    def once(self, event, f):
        self.emitter.once(event, f)

    def remove(self, event_name, func):
        pass

    def remove_all_listeners(self, event_name):
        pass
示例#6
0
class RegistrationOnlyEmitter(object):
    def __init__(self):
        self.emitter = EventEmitter()

    def on(self, event, f):
        allow_events_to_execute = True

        if allow_events_to_execute:
            # don't filter events, just run them all
            print "Event: "+str(event)
            self.emitter.on(event, f)
        else:
            # filter to just the registration events,
            # preventing them from actually executing
            if event in [
                'register_intent',
                'register_vocab',
                'recognizer_loop:utterance'
            ]:
                print "Event: " + str(event)
                self.emitter.on(event, f)

    def emit(self, event, *args, **kwargs):
        event_name = event.type
        self.emitter.emit(event_name, event, *args, **kwargs)

    def once(self, event, f):
        self.emitter.once(event, f)

    def remove(self, event_name, func):
        pass
class InterceptEmitter(object):
    """
    This class intercepts and allows emitting events between the
    skill_tester and the skill being tested.
    When a test is running emitted communication is intercepted for analysis
    """
    def __init__(self):
        self.emitter = EventEmitter()
        self.q = None

    def on(self, event, f):
        # run all events
        print("Event: ", event)
        self.emitter.on(event, f)

    def emit(self, event, *args, **kwargs):
        event_name = event.type
        if self.q:
            self.q.put(event)
        self.emitter.emit(event_name, event, *args, **kwargs)

    def once(self, event, f):
        self.emitter.once(event, f)

    def remove(self, event_name, func):
        pass

    def remove_all_listeners(self, event_name):
        pass
示例#8
0
class RegistrationOnlyEmitter(object):
    def __init__(self):
        self.emitter = EventEmitter()

    def on(self, event, f):
        allow_events_to_execute = True

        if allow_events_to_execute:
            # don't filter events, just run them all
            print "Event: " + str(event)
            self.emitter.on(event, f)
        else:
            # filter to just the registration events,
            # preventing them from actually executing
            if event in [
                    'register_intent', 'register_vocab',
                    'recognizer_loop:utterance'
            ]:
                print "Event: " + str(event)
                self.emitter.on(event, f)

    def emit(self, event, *args, **kwargs):
        event_name = event.type
        self.emitter.emit(event_name, event, *args, **kwargs)

    def once(self, event, f):
        self.emitter.once(event, f)

    def remove(self, event_name, func):
        pass
示例#9
0
class Camera()
    running = True

    def __init__(self,fps=24):
        self.emitter = EventEmitter()
        self.fps = fps
        self.cap = cv2.VideoCapture(0)
        self.thread = threading.Thread(target=self.run)
        self.thread.daemon = True
        self.thread.start()

    def run(self):
        capturePeriodSecs = 1.0 / self.fps
        while self.Running == True:
            try:
                self.cap_frame()
            except Exception as error:
                print ("error with capturing frames: ", error)
            time.sleep(capturePeriodSecs)

    def onNewFrame(self,callback):
        self.emitter.on('frame', callback)

    def removeOnNewFrameListener(self,callback):
        self.emitter.remove_emitter_listener('frame', callback)


    def stop(self):
        self.running = False


    def cap_frame(self):
        f,img = self.cap.read()
        self.latest_frame = img
        self.emitter.emit('frame', img)
示例#10
0
def addEventListener(emitter: EventEmitter, eventName: str, handler: Callable) -> Dict[(str, Any)]:
    'Add handler to the emitter and return emitter/handler.'
    emitter.on(eventName, handler)
    return {
        'emitter': emitter,
        'eventName': eventName,
        'handler': handler,
    }
示例#11
0
class RegistrationOnlyEmitter(object):
    def __init__(self):
        self.emitter = EventEmitter()

    def on(self, event, f):
        if event in ['register_intent', 'register_vocab', 'recognizer_loop:utterance']:
            self.emitter.on(event, f)

    def emit(self, event, *args, **kwargs):
        event_name = event.message_type
        self.emitter.emit(event_name, event, *args, **kwargs)
示例#12
0
def test_emit_return():
    ee = EventEmitter()

    # make sure emitting without a callback returns False
    nt.assert_false(ee.emit('data'))

    # add a callback
    ee.on('data')(lambda: None)

    # should return True now
    nt.assert_true(ee.emit('data'))
示例#13
0
def test_proxy_new_listener(proxy_new_listener):
    call_me = Mock()

    base_ee = EventEmitter()

    uplifted_ee = uplift(UpliftedEventEmitter,
                         base_ee,
                         proxy_new_listener=proxy_new_listener)

    @base_ee.on('new_listener')
    def base_new_listener_handler(event, f):
        assert event in ('event', 'new_listener')
        call_me('base new listener handler', f)

    @uplifted_ee.on('new_listener')
    def uplifted_new_listener_handler(event, f):
        assert event in ('event', 'new_listener')
        call_me('uplifted new listener handler', f)

    def fresh_base_handler():
        pass

    def fresh_uplifted_handler():
        pass

    base_ee.on('event', fresh_base_handler)
    uplifted_ee.on('event', fresh_uplifted_handler)

    if proxy_new_listener == 'both':
        call_me.assert_has_calls([
            call('base new listener handler', fresh_base_handler),
            call('uplifted new listener handler', fresh_base_handler),
            call('uplifted new listener handler', fresh_uplifted_handler),
            call('base new listener handler', fresh_uplifted_handler)
        ])
    elif proxy_new_listener == 'neither':
        call_me.assert_has_calls([
            call('base new listener handler', fresh_base_handler),
            call('uplifted new listener handler', fresh_uplifted_handler)
        ])
    elif proxy_new_listener == 'forward':
        call_me.assert_has_calls([
            call('base new listener handler', fresh_base_handler),
            call('uplifted new listener handler', fresh_base_handler),
            call('uplifted new listener handler', fresh_uplifted_handler)
        ])
    elif proxy_new_listener == 'backward':
        call_me.assert_has_calls([
            call('base new listener handler', fresh_base_handler),
            call('uplifted new listener handler', fresh_uplifted_handler),
            call('base new listener handler', fresh_uplifted_handler)
        ])
    else:
        raise Exception('unrecognized proxy_new_listener')
示例#14
0
    def wait_for_event(
        self,
        emitter: EventEmitter,
        event: str,
        predicate: Callable = None,
    ) -> None:
        def listener(event_data: Any = None) -> None:
            if not predicate or predicate(event_data):
                self._fulfill(event_data)

        emitter.on(event, listener)
        self._registered_listeners.append((emitter, event, listener))
def wait_for_event_future(
    emitter: EventEmitter, event: str, predicate: Callable[[Any], bool] = None
) -> asyncio.Future:
    future: asyncio.Future = asyncio.Future()

    def listener(event_data: Any = None) -> None:
        if not predicate or predicate(event_data):
            future.set_result(event_data)

    emitter.on(event, listener)

    future.add_done_callback(lambda f: emitter.remove_listener(event, listener))
    return future
示例#16
0
    def reject_on_event(
        self,
        emitter: EventEmitter,
        event: str,
        error: Error,
        predicate: Callable = None,
    ) -> None:
        def listener(event_data: Any = None) -> None:
            if not predicate or predicate(event_data):
                self._reject(error)

        emitter.on(event, listener)
        self._registered_listeners.append((emitter, event, listener))
示例#17
0
class RegistrationOnlyEmitter(object):
    def __init__(self):
        self.emitter = EventEmitter()

    def on(self, event, f):
        if event in [
                'register_intent', 'register_vocab',
                'recognizer_loop:utterance'
        ]:
            self.emitter.on(event, f)

    def emit(self, event, *args, **kwargs):
        event_name = event.message_type
        self.emitter.emit(event_name, event, *args, **kwargs)
示例#18
0
def test_new_listener_event():
    """The 'new_listener' event fires whenever a new listerner is added."""

    call_me = Mock()
    ee = EventEmitter()

    ee.on('new_listener', call_me)

    # Should fire new_listener event
    @ee.on('event')
    def event_handler(data):
        pass

    call_me.assert_called_once()
示例#19
0
def test_listener_removal_on_emit():
    """Test that a listener removed during an emit is called inside the current
    emit cycle.
    """

    call_me = Mock()
    ee = EventEmitter()

    def should_remove():
        ee.remove_listener('remove', call_me)

    ee.on('remove', should_remove)
    ee.on('remove', call_me)

    ee.emit('remove')

    call_me.assert_called_once()

    call_me.reset_mock()

    # Also test with the listeners added in the opposite order
    ee = EventEmitter()
    ee.on('remove', call_me)
    ee.on('remove', should_remove)

    ee.emit('remove')

    call_me.assert_called_once()
示例#20
0
def test_emit_return():
    """Emit returns True when handlers are registered on an event, and false
    otherwise.
    """

    call_me = Mock()
    ee = EventEmitter()

    # make sure emitting without a callback returns False
    assert not ee.emit('data')

    # add a callback
    ee.on('data')(call_me)

    # should return True now
    assert ee.emit('data')
class MessageBusEventHandler(WebSocketHandler):
    def __init__(self, application, request, **kwargs):
        super().__init__(application, request, **kwargs)
        self.emitter = EventEmitter()

    def on(self, event_name, handler):
        self.emitter.on(event_name, handler)

    def on_message(self, message):
        LOG.debug(message)
        try:
            deserialized_message = Message.deserialize(message)
        except Exception:
            return

        try:
            self.emitter.emit(deserialized_message.msg_type,
                              deserialized_message)
        except Exception as e:
            LOG.exception(e)
            traceback.print_exc(file=sys.stdout)
            pass

        for client in client_connections:
            client.write_message(message)

    def open(self):
        self.write_message(Message("connected").serialize())
        client_connections.append(self)

    def on_close(self):
        client_connections.remove(self)

    def emit(self, channel_message):
        if (hasattr(channel_message, 'serialize')
                and callable(getattr(channel_message, 'serialize'))):
            self.write_message(channel_message.serialize())
        else:
            self.write_message(json.dumps(channel_message))

    def check_origin(self, origin):
        return True
示例#22
0
class InterceptEmitter(object):
    """
    This class intercepts and allows emitting events between the
    skill_tester and the skill being tested.
    When a test is running emitted communication is intercepted for analysis
    """
    def __init__(self):
        self.emitter = EventEmitter()
        self.q = None

    def on(self, event, f):
        # run all events
        print("Event: ", event)
        self.emitter.on(event, f)

    def emit(self, event, *args, **kwargs):
        event_name = event.msg_type
        if self.q:
            self.q.put(event)
        self.emitter.emit(event_name, event, *args, **kwargs)

    def wait_for_response(self, event, reply_type=None, *args, **kwargs):
        """Simple single thread implementation of wait_for_response."""
        message_type = reply_type or event.msg_type + '.response'
        response = None

        def response_handler(msg):
            nonlocal response
            response = msg

        self.emitter.once(message_type, response_handler)
        self.emitter.emit(event.msg_type, event)
        return response

    def once(self, event, f):
        self.emitter.once(event, f)

    def remove(self, event_name, func):
        pass

    def remove_all_listeners(self, event_name):
        pass
class MockWebsocket():
    def __init__(self):
        self.events = EventEmitter(scheduler=asyncio.ensure_future)
        self.saved_items = []
        self.emitted_items = []

    def on(self, *args, **kwargs):
        self.events.on(*args, **kwargs)

    def once(self, *args, **kwargs):
        self.events.once(*args, **kwargs)

    def _emit(self, event, *args, **kwargs):
        # save published items for testing
        self.emitted_items += [{
            'time': int(round(time.time() * 1000)),
            'data': {
                'event': event,
                'args': args,
                'kwargs': kwargs
            }
        }]
        self.events.emit(event, *args, **kwargs)

    def remove_all_listeners(self, *args, **kwargs):
        self.events.remove_all_listeners(*args, **kwargs)

    def cancel_order(self, *args, **kawargs):
        pass

    def submit_order(self, *args, **kawargs):
        pass

    def get_emitted_items(self):
        return self.emitted_items

    def get_last_emitted_item(self):
        return self.emitted_items[-1:][0]

    def get_emitted_items_count(self):
        return len(self.emitted_items)
示例#24
0
class Sensor(Component):
    """A sensor abstraction component interface."""

    def __init__(self, pin):
        """Initialize a new instance of Sensor.

        :param raspy.io.gpio.Gpio pin: The input pin to sample data from.
        :raises: ArgumentNullException if 'pin' param is None.
        """
        Component.__init__(self)
        if pin is None:
            raise ArgumentNullException("'pin' param cannot be None.")

        self.__emitter = EventEmitter()
        self.__state = sensor_state.OPEN
        self.__pin = pin
        self.__pin.provision()

    def dispose(self):
        """Release managed resources used by this component."""
        if self.is_disposed:
            return

        if self.__pin is not None:
            self.__pin.dispose()
            self.__pin = None

        self.__state = sensor_state.OPEN
        self.__emitter.remove_all_listeners()
        self.__emitter = None
        Component.dispose(self)

    def on(self, evt, callback):
        """Register an event with a callback to handle it.

        :param str evt: The name of the event to register a handler for.
        :param function callback: The callback to execute when the event
        fires.
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Sensor")

        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Emit the specified event to all registered listeners.

        :param str evt: The name of the event to emit.
        :param object args: The arguments to pass to the event handlers
        (listeners).
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Sensor")

        self.__emitter.emit(evt, args)

    def remove_all_listeners(self):
        """Remove all registered event listeners."""
        if self.is_disposed:
            return

        if self.__emitter is not None:
            self.__emitter.remove_all_listeners()

    def on_sensor_state_change(self, change_evt):
        """Fire the sensor state change event.

        :param sensor_state_change_event.SensorStateChangeEvent change_evt:
        The state change event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Sensor")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_STATE_CHANGED,
                              args=(EVENT_STATE_CHANGED, change_evt))
        _t.daemon = True
        _t.start()

    @property
    def state(self):
        """Get the state of the sensor.

        :returns: The sensor state.
        :rtype: int
        """
        return self.__state

    def is_state(self, sens_state):
        """Check to see if the sensor is in the specified state.

        :param int sens_state: The state to check.
        :returns: True if in the specified state.
        :rtype: bool
        """
        return self.state == sens_state

    @property
    def is_open(self):
        """Get a value indicating whether this is sensor is open.

        :returns: True if open; Otherwise, False.
        :rtype: bool
        """
        return self.is_state(sensor_state.OPEN)

    @property
    def is_closed(self):
        """Get a value indicating whether this sensor is closed.

        :returns: True if closed; Otherwise, False.
        :rtype: bool
        """
        return self.is_state(sensor_state.CLOSED)

    @property
    def pin(self):
        """Get the pin being used to sample sensor data.

        :returns: The underlying physical pin.
        :type: raspy.io.gpio.Gpio
        """
        return self.__pin
示例#25
0
class WebsocketClient(object):
    def __init__(self, host=None, port=None, route=None, ssl=None):

        config = Configuration.get().get("websocket")
        host = host or config.get("host")
        port = port or config.get("port")
        route = route or config.get("route")
        ssl = ssl or config.get("ssl")
        validate_param(host, "websocket.host")
        validate_param(port, "websocket.port")
        validate_param(route, "websocket.route")

        self.url = WebsocketClient.build_url(host, port, route, ssl)
        self.emitter = EventEmitter()
        self.client = self.create_client()
        self.pool = ThreadPool(10)
        self.retry = 5

    @staticmethod
    def build_url(host, port, route, ssl):
        scheme = "wss" if ssl else "ws"
        return scheme + "://" + host + ":" + str(port) + route

    def create_client(self):
        return WebSocketApp(self.url,
                            on_open=self.on_open, on_close=self.on_close,
                            on_error=self.on_error, on_message=self.on_message)

    def on_open(self, ws):
        LOG.info("Connected")
        self.emitter.emit("open")
        # Restore reconnect timer to 5 seconds on sucessful connect
        self.retry = 5

    def on_close(self, ws):
        self.emitter.emit("close")

    def on_error(self, ws, error):
        try:
            self.emitter.emit('error', error)
            self.client.close()
        except Exception as e:
            LOG.error(repr(e))
        LOG.warning("WS Client will reconnect in %d seconds." % self.retry)
        time.sleep(self.retry)
        self.retry = min(self.retry * 2, 60)
        self.client = self.create_client()
        self.run_forever()

    def on_message(self, ws, message):
        self.emitter.emit('message', message)
        parsed_message = Message.deserialize(message)
        self.pool.apply_async(
            self.emitter.emit, (parsed_message.type, parsed_message))

    def emit(self, message):
        if (not self.client or not self.client.sock or
                not self.client.sock.connected):
            return
        if hasattr(message, 'serialize'):
            self.client.send(message.serialize())
        else:
            self.client.send(json.dumps(message.__dict__))

    def on(self, event_name, func):
        self.emitter.on(event_name, func)

    def once(self, event_name, func):
        self.emitter.once(event_name, func)

    def remove(self, event_name, func):
        self.emitter.remove_listener(event_name, func)

    def remove_all_listeners(self, event_name):
        '''
            Remove all listeners connected to event_name.

            Args:
                event_name: event from which to remove listeners
        '''
        if event_name is None:
            raise ValueError
        self.emitter.remove_all_listeners(event_name)

    def run_forever(self):
        self.client.run_forever()

    def close(self):
        self.client.close()
示例#26
0
class WebsocketClient(object):
    def __init__(self, host=None, port=None, route=None, ssl=None):

        config = Configuration.get().get("websocket")
        host = host or config.get("host")
        port = port or config.get("port")
        route = route or config.get("route")
        ssl = ssl or config.get("ssl")
        validate_param(host, "websocket.host")
        validate_param(port, "websocket.port")
        validate_param(route, "websocket.route")

        self.url = WebsocketClient.build_url(host, port, route, ssl)
        self.emitter = EventEmitter()
        self.client = self.create_client()
        self.pool = ThreadPool(10)
        self.retry = 5
        self.connected_event = Event()
        self.started_running = False

    @staticmethod
    def build_url(host, port, route, ssl):
        scheme = "wss" if ssl else "ws"
        return scheme + "://" + host + ":" + str(port) + route

    def create_client(self):
        return WebSocketApp(self.url,
                            on_open=self.on_open, on_close=self.on_close,
                            on_error=self.on_error, on_message=self.on_message)

    def on_open(self, ws):
        LOG.info("Connected")
        self.connected_event.set()
        self.emitter.emit("open")
        # Restore reconnect timer to 5 seconds on sucessful connect
        self.retry = 5

    def on_close(self, ws):
        self.emitter.emit("close")

    def on_error(self, ws, error):
        try:
            self.emitter.emit('error', error)
            self.client.close()
        except Exception as e:
            LOG.error(repr(e))
        LOG.warning("WS Client will reconnect in %d seconds." % self.retry)
        time.sleep(self.retry)
        self.retry = min(self.retry * 2, 60)
        self.client = self.create_client()
        self.run_forever()

    def on_message(self, ws, message):
        self.emitter.emit('message', message)
        parsed_message = Message.deserialize(message)
        self.pool.apply_async(
            self.emitter.emit, (parsed_message.type, parsed_message))

    def emit(self, message):
        if not self.connected_event.wait(10):
            if not self.started_running:
                raise ValueError('You must execute run_forever() '
                                 'before emitting messages')
            self.connected_event.wait()

        if hasattr(message, 'serialize'):
            self.client.send(message.serialize())
        else:
            self.client.send(json.dumps(message.__dict__))

    def wait_for_response(self, message, reply_type=None, timeout=None):
        """Send a message and wait for a response.

        Args:
            message (Message): message to send
            reply_type (str): the message type of the expected reply.
                              Defaults to "<message.type>.response".
            timeout: seconds to wait before timeout, defaults to 3
        Returns:
            The received message or None if the response timed out
        """
        response = []

        def handler(message):
            """Receive response data."""
            response.append(message)

        # Setup response handler
        self.once(reply_type or message.type + '.response', handler)
        # Send request
        self.emit(message)
        # Wait for response
        start_time = monotonic.monotonic()
        while len(response) == 0:
            time.sleep(0.2)
            if monotonic.monotonic() - start_time > (timeout or 3.0):
                try:
                    self.remove(reply_type, handler)
                except (ValueError, KeyError):
                    # ValueError occurs on pyee 1.0.1 removing handlers
                    # registered with once.
                    # KeyError may theoretically occur if the event occurs as
                    # the handler is removbed
                    pass
                return None
        return response[0]

    def on(self, event_name, func):
        self.emitter.on(event_name, func)

    def once(self, event_name, func):
        self.emitter.once(event_name, func)

    def remove(self, event_name, func):
        self.emitter.remove_listener(event_name, func)

    def remove_all_listeners(self, event_name):
        '''
            Remove all listeners connected to event_name.

            Args:
                event_name: event from which to remove listeners
        '''
        if event_name is None:
            raise ValueError
        self.emitter.remove_all_listeners(event_name)

    def run_forever(self):
        self.started_running = True
        self.client.run_forever()

    def close(self):
        self.client.close()
        self.connected_event.clear()
class GenericWebsocket:
    """
    Websocket object used to contain the base functionality of a websocket.
    Inlcudes an event emitter and a standard websocket client.
    """

    def __init__(self, host, logLevel='INFO', loop=None):
        self.host = host
        self.logger = CustomLogger('BfxWebsocket', logLevel=logLevel)
        self.loop = loop or asyncio.get_event_loop()
        self.events = EventEmitter(
            scheduler=asyncio.ensure_future, loop=self.loop)
        self.ws = None

    def run(self):
        """
        Run the websocket connection indefinitely
        """
        self.loop.run_until_complete(self._main(self.host))

    def get_task_executable(self):
        """
        Get the run indefinitely asyncio task
        """
        return self._main(self.host)

    async def _main(self, host):
        async with websockets.connect(host) as websocket:
            self.ws = websocket
            self.logger.info("Wesocket connectedt to {}".format(self.host))
            while True:
                await asyncio.sleep(0)
                message = await websocket.recv()
                await self.on_message(message)

    def remove_all_listeners(self, event):
        """
        Remove all listeners from event emitter
        """
        self.events.remove_all_listeners(event)

    def on(self, event, func=None):
        """
        Add a new event to the event emitter
        """
        if not func:
            return self.events.on(event)
        self.events.on(event, func)

    def once(self, event, func=None):
        """
        Add a new event to only fire once to the event
        emitter
        """
        if not func:
            return self.events.once(event)
        self.events.once(event, func)

    def _emit(self, event, *args, **kwargs):
        self.events.emit(event, *args, **kwargs)

    async def on_error(self, error):
        """
        On websocket error print and fire event
        """
        self.logger.error(error)
        self.events.emit('error', error)

    async def on_close(self):
        """
        On websocket close print and fire event
        """
        self.logger.info("Websocket closed.")
        await self.ws.close()
        self._emit('done')

    async def on_open(self):
        """
        On websocket open
        """
        pass

    async def on_message(self, message):
        """
        On websocket message
        """
        pass
示例#28
0
class GenericWebsocket:
    """
    Websocket object used to contain the base functionality of a websocket.
    Inlcudes an event emitter and a standard websocket client.
    """
    def __init__(self, host, logLevel='INFO', loop=None, max_retries=5):
        self.host = host
        self.logger = CustomLogger('BfxWebsocket', logLevel=logLevel)
        self.loop = loop or asyncio.get_event_loop()
        self.events = EventEmitter(scheduler=asyncio.ensure_future,
                                   loop=self.loop)
        # overide 'error' event to stop it raising an exception
        # self.events.on('error', self.on_error)
        self.ws = None
        self.max_retries = max_retries
        self.attempt_retry = True

    def run(self):
        """
        Run the websocket connection indefinitely
        """
        self.loop.run_until_complete(self._main(self.host))

    def get_task_executable(self):
        """
        Get the run indefinitely asyncio task
        """
        return self._main(self.host)

    async def _connect(self, host):
        async with websockets.connect(host) as websocket:
            self.ws = websocket
            self.logger.info("Wesocket connected to {}".format(host))
            while True:
                await asyncio.sleep(0)
                message = await websocket.recv()
                await self.on_message(message)

    def get_ws(self):
        return self.ws

    async def _main(self, host):
        retries = 0
        while retries < self.max_retries and self.attempt_retry:
            try:
                await self._connect(host)
                retries = 0
            except (ConnectionClosed, socket.error) as e:
                self._emit('disconnected')
                if (not self.attempt_retry):
                    return
                self.logger.error(str(e))
                retries += 1
                # wait 5 seconds befor retrying
                self.logger.info("Waiting 5 seconds before retrying...")
                await asyncio.sleep(5)
                self.logger.info("Reconnect attempt {}/{}".format(
                    retries, self.max_retries))
        self.logger.info("Unable to connect to websocket.")
        self._emit('stopped')

    def remove_all_listeners(self, event):
        """
        Remove all listeners from event emitter
        """
        self.events.remove_all_listeners(event)

    def on(self, event, func=None):
        """
        Add a new event to the event emitter
        """
        if not func:
            return self.events.on(event)
        self.events.on(event, func)

    def once(self, event, func=None):
        """
        Add a new event to only fire once to the event
        emitter
        """
        if not func:
            return self.events.once(event)
        self.events.once(event, func)

    def _emit(self, event, *args, **kwargs):
        self.events.emit(event, *args, **kwargs)

    async def on_error(self, error):
        """
        On websocket error print and fire event
        """
        self.logger.error(error)

    async def on_close(self):
        """
        On websocket close print and fire event. This is used by the data server.
        """
        self.logger.info("Websocket closed.")
        self.attempt_retry = False
        await self.ws.close()
        self._emit('done')

    async def on_open(self):
        """
        On websocket open
        """
        pass

    async def on_message(self, message):
        """
        On websocket message
        """
        pass
示例#29
0
class Fireplace(Device):
    """Fireplace device abstraction interface/base type."""
    def __init__(self):
        """Initialize a new instance of Fireplace."""
        Device.__init__(self)
        self.__emitter = EventEmitter()
        self.__timeoutDelay = 0
        self.__timeoutDelayMillis = 0
        self.__timeoutUnit = time_unit.MINUTES
        self.__taskTimer = None
        self.__killTimer = None
        self.__state = fireplace_state.OFF
        self.__emitter.on(EVENT_STATE_CHANGED,
                          lambda evt: self._internal_state_changed(evt))

    def _cancel_timeout_task(self):
        """Cancel the timeout task (if running)."""
        if self.__taskTimer is not None:
            self.__taskTimer.cancel()
            self.__taskTimer = None

    def _internal_state_changed(self, evt):
        """An internal handler for the state change event.

        :param raspy.devices.fireplaces.fireplace_state_change_event.FireplaceStateChangeEvent evt:
        The event object.
        """
        if evt:
            pass
        self._cancel_timeout_task()

    def on(self, evt, callback):
        """Register an event with a callback to handle it.

        :param str evt: The name of the event to register a handler for.
        :param function callback: The callback to execute when the event
        fires.
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Fireplace")

        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Emit the specified event to all registered listeners.

        :param str evt: The name of the event to emit.
        :param object args: The arguments to pass to the event handlers
        (listeners).
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Fireplace")

        self.__emitter.emit(evt, args)

    def remove_all_listeners(self):
        """Remove all registered event listeners."""
        if self.is_disposed:
            return

        if self.__emitter is not None:
            self.__emitter.remove_all_listeners()

    def on_state_change(self, evt):
        """Fire the state change event.

        :param raspy.devices.fireplaces.fireplace_state_change_event.FireplaceStateChangeEvent evt:
        The event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Fireplace")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_STATE_CHANGED,
                              args=(EVENT_STATE_CHANGED, evt))
        _t.daemon = True
        _t.start()

    def on_operation_timeout(self, evt):
        """Fire the operation timeout event.

        :param raspy.devices.fireplaces.fireplace_timeout_event.FireplaceTimeoutEvent evt:
        The event object.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Fireplace")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_OPERATION_TIMEOUT,
                              args=(EVENT_OPERATION_TIMEOUT, evt))
        _t.daemon = True
        _t.start()

    def on_pilot_light_state_change(self, evt):
        """Fire the pilot light state change event.

        :param raspy.devices.fireplaces.fireplace_pilot_light_event.FireplacePilotLightEvent evt:
        The event object.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Fireplace")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_PILOT_LIGHT_STATE_CHANGED,
                              args=(EVENT_PILOT_LIGHT_STATE_CHANGED, evt))
        _t.daemon = True
        _t.start()

    @property
    def state(self):
        """Get the fireplace state.

        :returns: The fireplace state.
        :rtype: int
        """
        return self.__state

    @state.setter
    def state(self, the_state):
        """Set the fireplace state.

        :param int the_state: The fireplace state.
        :raises: .fireplace_pilot_light_exception.FireplacePilotLightException if
        no pilot light sensor is present.
        """
        self.__state = the_state

    @property
    def is_on(self):
        """Get a flag indicating whether the fireplace is on.

        :returns: True if the fireplace is on.
        :rtype: bool
        """
        return self.state == fireplace_state.ON

    @property
    def is_off(self):
        """Get a flag indicating whether the fireplace is off.

        :returns: True if the fireplace is off.
        :rtype: bool
        """
        return self.state == fireplace_state.OFF

    @property
    def is_pilot_light_on(self):
        """Get a flag indicating whether the pilot light is on.

        :returns: True if the pilot light is on.
        :rtype: bool
        """
        return False

    @property
    def is_pilot_light_off(self):
        """Get a flag indicating whether the pilot light is off.

        :returns: True if the pilot light is off.
        :rtype: bool
        """
        return False

    def get_timeout_delay(self):
        """Get the timeout delay.

        :returns: The timeout delay.
        :type: int
        """
        return self.__timeoutDelay

    def get_timeout_unit(self):
        """Get the timeout unit of time.

        :returns: The time unit being used for the timeout delay.
        :rtype: int
        """
        return self.__timeoutUnit

    def set_timeout_delay(self, delay, unit):
        """Get the timeout delay.

        :param int delay: The timeout delay.
        :param int unit: The time unit of measure for the timeout.
        :raises: raspy.invalid_operation_exception.InvalidOperationException if
        the fireplace is turned off.
        """
        if self.is_off:
            msg = "Cannot set timeout when the fireplace is off."
            raise InvalidOperationException(msg)

        self.__timeoutDelay = delay
        self.__timeoutUnit = unit
        self.cancel_timeout()
        if self.__timeoutDelay > 0:
            wait_time = datetime.timedelta()
            if unit == time_unit.DAYS:
                wait_time = datetime.timedelta(days=delay)
            elif unit == time_unit.HOURS:
                wait_time = datetime.timedelta(hours=delay)
            elif unit == time_unit.MINUTES:
                wait_time = datetime.timedelta(minutes=delay)
            elif unit == time_unit.SECONDS:
                wait_time = datetime.timedelta(seconds=delay)
            elif unit == time_unit.MILLISECONDS:
                wait_time = datetime.timedelta(milliseconds=delay)

            kill_delay = datetime.timedelta(
                milliseconds=wait_time.total_seconds())
            kill_delay += datetime.timedelta(seconds=1)
            sec = kill_delay.total_seconds()
            self.__killTimer = threading.Timer(sec, self._cancel_timeout_task)
            self.__killTimer.start()
            self._start_cancel_task()

    def turn_on(self, timeout_delay, timeout_unit):
        """Turn the fireplace on with the specified timeout.

        If the operation is not successful within the allotted time, the
        operation is cancelled for safety reasons.

        :param int timeout_delay: The timeout delay. If not specified or
        less than or equal to zero, then the fireplace is turned on without
        any safety delay (not recommended).
        :param int timeout_unit: The time unit of measure for the timeout. If
        not specified, `time_unit.SECONDS` is assumed.
        """
        self.state = fireplace_state.ON
        if timeout_unit is None:
            timeout_unit = self.__timeoutUnit

        if timeout_delay is not None:
            if timeout_delay > 0:
                self.set_timeout_delay(timeout_delay, timeout_unit)

    def turn_off(self):
        """Turn the fireplace off."""
        self.state = fireplace_state.OFF

    def _task_action(self):
        """The action for the background timeout task.

        This fires the operation timeout event, then turns off the fireplace.
        """
        evt = FireplaceTimeoutEvent()
        self.on_operation_timeout(evt)
        if not evt.is_handled:
            self.turn_off()

    def _do_task(self):
        self._task_action()
        self.__killTimer.cancel()
        self.__killTimer = None

    def _start_cancel_task(self):
        """Start the background cancellation task."""
        if self.__killTimer is not None:
            self.__taskTimer = threading.Timer(self.__timeoutDelayMillis,
                                               self._do_task)
            self.__taskTimer.start()

    def cancel_timeout(self):
        """Cancel the timeout."""
        self._cancel_timeout_task()

    def shutdown(self):
        """Shutdown the fireplace."""
        self.cancel_timeout()
        self.turn_off()

    def dispose(self):
        """Release all managed resources used by this component."""
        if self.is_disposed:
            return

        self._cancel_timeout_task()
        if self.__killTimer is not None:
            self.__killTimer.cancel()
            self.__killTimer = None

        self.__emitter.remove_all_listeners()
        self.__emitter = None
        self.__state = fireplace_state.OFF
        self.__timeoutDelay = 0
        self.__timeoutDelayMillis = 0
        Device.dispose(self)
示例#30
0
class PiCameraDevice(Device):
    """An abstraction of the RaspiCam device.

    RaspiCam is a peripheral camera device designed specifically for use with
    the Raspberry Pi. This class provides a threaded wrapper around the
    raspistill utility and thus a means for still capture control. See
    http://www.raspberrypi.org/wp-content/uploads/2013/07/RaspiCam-Documentation.pdf
    for instructions on how to install and configure RaspiCam support.
    """
    def __init__(self, settings=None):
        """Initialize a new instance of PiCameraDevice.

        :param StillCaptureSettings settings: The image capture settings.
        """
        Device.__init__(self)
        self.__settings = settings
        self.__emitter = EventEmitter()
        self.__isRunning = False
        self.__processID = -1
        self.__exitCode = -1
        self.__captureProc = None
        self.__syncLock = threading.RLock()
        self.__captureThread = None

    def on(self, evt, callback):
        """Register an event with a callback to handle it.

        :param str evt: The name of the event to register a handler for.
        :param function callback: The callback to execute when the event
        fires.
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiCameraDevice")

        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Emit the specified event to all registered listeners.

        :param str evt: The name of the event to emit.
        :param object args: The arguments to pass to the event handlers
        (listeners).
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Gpio")

        self.__emitter.emit(evt, args)

    def remove_all_listeners(self):
        """Remove all registered event listeners."""
        if self.is_disposed:
            return

        if self.__emitter is not None:
            self.__emitter.remove_all_listeners()

    @property
    def capture_settings(self):
        """Get the still capture settings.

        :returns: The still capture settings.
        :rtype: StillCaptureSettings
        """
        return self.__settings

    @capture_settings.setter
    def capture_settings(self, settings):
        """Set the still capture settings.

        :param StillCaptureSettings settings: The capture settings.
        """
        self.__settings = settings

    @property
    def process_id(self):
        """Get the process ID.

        :returns: The ID of the capture process if started;
        Otherwise, -1.
        :rtype: int
        """
        return self.__processID

    @property
    def is_running(self):
        """Get whether or not the capture process is running.

        :returns: True if running.
        :rtype: bool
        """
        return self.__isRunning

    @property
    def exit_code(self):
        """Get the exit code of the capture process.

        :returns: The process exit code if terminated normally;
        Otherwise, -1.
        """
        return self.__exitCode

    def on_capture_started(self, start_evt):
        """Fire the capture started event.

        :param CaptureStartEvent start_evt: The event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiCameraDevice")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_CAPTURE_START,
                              args=(EVENT_CAPTURE_START, start_evt))
        _t.daemon = True
        _t.start()

    def on_capture_output_received(self, out_evt):
        """Fire the capture output event.

        :param CaptureOutputEvent out_evt: The event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiCameraDevice")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_CAPTURE_OUTPUT,
                              args=(EVENT_CAPTURE_OUTPUT, out_evt))
        _t.daemon = True
        _t.start()

    def on_capture_done(self, done_evt):
        """Fire the capture done event.

        :param CaptureDoneEvent done_evt: The event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("PiCameraDevice")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_CAPTURE_DONE,
                              args=(EVENT_CAPTURE_DONE, done_evt))
        _t.daemon = True
        _t.start()

    def cancel(self):
        """Cancel the still capture process, if running.

        Should emit EVENT_CAPTURE_DONE and include the termination signal.
        """
        if not self.__isRunning:
            return

        self.__syncLock.acquire()
        self.__isRunning = False
        self.__syncLock.release()
        core_utils.sleep(500)
        if self.__captureProc is not None:
            if self.__captureProc.poll() is not None:
                try:
                    self.__captureProc.kill()
                except OSError:
                    # Process probably already died.
                    pass

    @staticmethod
    def _enqueue_output(out, queue):
        """Enqueue output from the process.

        :param File out: The standard output stream from the process.
        :param Queue queue: The queue to store the output lines in.
        """
        for line in iter(out.readline, b''):
            queue.put(line)
        out.close()

    def _monitor_capture(self):
        """Monitor the capture process."""
        if self.__settings is None:
            self.__settings = StillCaptureSettings()

        args = self.__settings.to_argument_string()
        cmd = ['raspistill'] + args.split(" ")

        # start the process and get the PID.
        on_posix = 'posix' in sys.builtin_module_names
        self.__captureProc = Popen(cmd,
                                   stdout=PIPE,
                                   stderr=PIPE,
                                   bufsize=1,
                                   close_fds=on_posix)
        read_queue = Queue()
        enqueue_args = (self.__captureProc.stdout, read_queue)
        queue_thread = threading.Thread(target=PiCameraDevice._enqueue_output,
                                        args=enqueue_args)
        queue_thread.daemon = True
        queue_thread.start()
        self.__syncLock.acquire()
        self.__processID = self.__captureProc.pid
        self.__syncLock.release()

        # Notify listeners that the process started and start signaling output.
        self.on_capture_started(CaptureStartEvent(self.__processID))
        while self.__captureProc.poll() is None:
            try:
                line = read_queue.get_nowait()
            except Empty:
                pass
            else:
                self.on_capture_output_received(CaptureOutputEvent(line))

        # The process finished. Get the exit code.
        self.__syncLock.acquire()
        self.__exitCode = self.__captureProc.returncode
        self.__isRunning = False
        self.__syncLock.release()

        # Notify listeners that the process finished.
        self.on_capture_done(CaptureDoneEvent(self.__exitCode))

    def start(self):
        """Start the capture process on a separate thread.

        This method immediately returns and the process continues in the
        background firing events as they occur.
        """
        if self.is_running:
            return

        self.__processID = -1
        self.__exitCode = 0
        self.__captureThread = threading.Thread(target=self._monitor_capture)
        self.__captureThread.name = "raspistillMonitor"
        self.__captureThread.daemon = True
        self.__captureThread.start()
        self.__isRunning = True

    def dispose(self):
        """Release managed resources used by this component."""
        if self.is_disposed:
            return

        self.cancel()
        self.__captureThread = None
        self.__exitCode = 0
        self.__processID = -1
        self.__syncLock = None
        self.__captureProc = None
        self.__settings = None
        self.__emitter.remove_all_listeners()
        self.__emitter = None
        Device.dispose(self)
示例#31
0
class Opener(Device):
    """Opener device abstraction interface."""
    def __init__(self):
        """Initialize a new instance of Opener."""
        Device.__init__(self)
        self.__emitter = EventEmitter()
        self.__state = opener_state.CLOSED

    def on(self, evt, callback):
        """Register an event with a callback to handle it.

        :param str evt: The name of the event to register a handler for.
        :param function callback: The callback to execute when the event
        fires.
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Opener")

        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Emit the specified event to all registered listeners.

        :param str evt: The name of the event to emit.
        :param object args: The arguments to pass to the event handlers
        (listeners).
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Opener")

        self.__emitter.emit(evt, args)

    def remove_all_listeners(self):
        """Remove all registered event listeners."""
        if self.is_disposed:
            return

        if self.__emitter is not None:
            self.__emitter.remove_all_listeners()

    def on_opener_state_change(self, change_evt):
        """Fire the opener state change event.

        :param raspy.devices.access.opener_state_change_event.OpenerStateChangeEvent change_evt:
        The event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Opener")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_STATE_CHANGED,
                              args=(EVENT_STATE_CHANGED, change_evt))
        _t.daemon = True
        _t.start()

    def on_lock_state_change(self, change_evt):
        """Fire the lock state change event.

        :param raspy.devices.access.opener_lock_change_event.OpenerLockChangeEvent change_evt:
        The event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Opener")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_LOCK_STATE_CHANGED,
                              args=(EVENT_LOCK_STATE_CHANGED, change_evt))
        _t.daemon = True
        _t.start()

    @property
    def state(self):
        """Get the state of the opener.

        :returns: The opener state.
        :rtype: int
        """
        return self.__state

    @property
    def is_open(self):
        """Get a flag indicating whether the opener is open.

        :returns: True if open; Otherwise, False.
        :rtype: bool
        """
        return self.state == opener_state.OPEN

    @property
    def is_opening(self):
        """Get a flag indicating if in the process of opening.

        :returns: True if opening; Otherwise, False.
        :rtype: bool
        """
        return self.state == opener_state.OPENING

    @property
    def is_closed(self):
        """Get a flag indicating whether this opener is closed.

        :returns: True if closed; Otherwise, False.
        :rtype: bool
        """
        return self.state == opener_state.CLOSED

    @property
    def is_closing(self):
        """Get a flag indicating if in the process of closing.

        :returns: True if closing; Otherwise, False.
        :rtype: bool
        """
        return self.state == opener_state.CLOSING

    @property
    def is_locked(self):
        """Get a flag indicating whether this opener is locked.

        :returns: True if locked; Otherwise, False.
        :rtype: bool
        """
        return False

    def open(self):
        """Instruct the device to open.

        :raises: ObjectDisposedException if this instance has been disposed.
        """
        raise NotImplementedError("Method 'open()' not implemented.")

    def close(self):
        """Instruct the device to close.

        :raises: ObjectDisposedException if this instance has been disposed.
        """
        raise NotImplementedError("Method 'close()' not implemented.")

    def dispose(self):
        """Release managed resources used by this component."""
        if self.is_disposed:
            return

        self.__emitter.remove_all_listeners()
        self.__emitter = None
        self.__state = opener_state.CLOSED
        Device.dispose(self)
示例#32
0
class GenericWebsocket:
    """
    Websocket object used to contain the base functionality of a websocket.
    Inlcudes an event emitter and a standard websocket client.
    """
    def __init__(self,
                 host,
                 logLevel='INFO',
                 loop=None,
                 max_retries=5,
                 create_event_emitter=_start_event_worker):
        self.host = host
        self.logger = CustomLogger('BfxWebsocket', logLevel=logLevel)
        self.loop = loop or asyncio.get_event_loop()
        # overide 'error' event to stop it raising an exception
        # self.events.on('error', self.on_error)
        self.ws = None
        self.max_retries = max_retries
        self.attempt_retry = True
        self.sockets = {}
        # start seperate process for the even emitter
        eventLoop = create_event_emitter()
        self.events = EventEmitter(scheduler=asyncio.ensure_future,
                                   loop=eventLoop)

    def run(self):
        """
        Starte the websocket connection. This functions spawns the initial socket
        thread and connection.
        """
        self._start_new_socket()

    def get_task_executable(self):
        """
        Get the run indefinitely asyncio task
        """
        return self._run_socket()

    def _start_new_socket(self, socketId=None):
        if not socketId:
            socketId = len(self.sockets)

        def start_loop(loop):
            asyncio.set_event_loop(loop)
            loop.run_until_complete(self._run_socket())

        worker_loop = asyncio.new_event_loop()
        worker = Thread(target=start_loop, args=(worker_loop, ))
        worker.start()
        return socketId

    def _wait_for_socket(self, socket_id):
        """
        Block until the given socket connection is open
        """
        while True:
            socket = self.sockets.get(socket_id, False)
            if socket:
                if socket.isConnected and socket.ws:
                    return
            time.sleep(0.01)

    async def _connect(self, socket):
        async with websockets.connect(self.host) as websocket:
            self.sockets[socket.id].set_websocket(websocket)
            self.sockets[socket.id].set_connected()
            self.logger.info("Wesocket connected to {}".format(self.host))
            while True:
                await asyncio.sleep(0)
                message = await websocket.recv()
                await self.on_message(socket.id, message)

    def get_socket(self, socketId):
        return self.sockets[socketId]

    def get_authenticated_socket(self):
        for socketId in self.sockets:
            if self.sockets[socketId].isAuthenticated:
                return self.sockets[socketId]
        return None

    async def _run_socket(self):
        retries = 0
        sId = len(self.sockets)
        s = Socket(sId)
        self.sockets[sId] = s
        while retries < self.max_retries and self.attempt_retry:
            try:
                await self._connect(s)
                retries = 0
            except (ConnectionClosed, socket.error) as e:
                self.sockets[sId].set_disconnected()
                self._emit('disconnected')
                if (not self.attempt_retry):
                    return
                self.logger.error(str(e))
                retries += 1
                # wait 5 seconds befor retrying
                self.logger.info("Waiting 5 seconds before retrying...")
                await asyncio.sleep(5)
                self.logger.info("Reconnect attempt {}/{}".format(
                    retries, self.max_retries))
        self.logger.info("Unable to connect to websocket.")
        self._emit('stopped')

    def remove_all_listeners(self, event):
        """
        Remove all listeners from event emitter
        """
        self.events.remove_all_listeners(event)

    def on(self, event, func=None):
        """
        Add a new event to the event emitter
        """
        if not func:
            return self.events.on(event)
        self.events.on(event, func)

    def once(self, event, func=None):
        """
        Add a new event to only fire once to the event
        emitter
        """
        if not func:
            return self.events.once(event)
        self.events.once(event, func)

    def _emit(self, event, *args, **kwargs):
        self.events.emit(event, *args, **kwargs)

    async def on_error(self, error):
        """
        On websocket error print and fire event
        """
        self.logger.error(error)

    async def on_close(self):
        """
        On websocket close print and fire event. This is used by the data server.
        """
        self.logger.info("Websocket closed.")
        self.attempt_retry = False
        await self.ws.close()
        self._emit('done')

    async def on_open(self):
        """
        On websocket open
        """
        pass

    async def on_message(self, message):
        """
        On websocket message
        """
        pass
示例#33
0
class WebsocketClient:
    def __init__(self, host=None, port=None, route=None, ssl=None):

        config = Configuration.get().get("websocket")
        host = host or config.get("host")
        port = port or config.get("port")
        route = route or config.get("route")
        ssl = ssl or config.get("ssl")
        validate_param(host, "websocket.host")
        validate_param(port, "websocket.port")
        validate_param(route, "websocket.route")

        self.url = WebsocketClient.build_url(host, port, route, ssl)
        self.emitter = EventEmitter()
        self.client = self.create_client()
        self.pool = ThreadPool(10)
        self.retry = 5
        self.connected_event = Event()
        self.started_running = False

    @staticmethod
    def build_url(host, port, route, ssl):
        scheme = "wss" if ssl else "ws"
        return scheme + "://" + host + ":" + str(port) + route

    def create_client(self):
        return WebSocketApp(self.url,
                            on_open=self.on_open, on_close=self.on_close,
                            on_error=self.on_error, on_message=self.on_message)

    def on_open(self, ws):
        LOG.info("Connected")
        self.connected_event.set()
        self.emitter.emit("open")
        # Restore reconnect timer to 5 seconds on sucessful connect
        self.retry = 5

    def on_close(self, ws):
        self.emitter.emit("close")

    def on_error(self, ws, error):
        """ On error start trying to reconnect to the websocket. """
        if isinstance(error, WebSocketConnectionClosedException):
            LOG.warning('Could not send message because connection has closed')
        else:
            LOG.exception('=== ' + repr(error) + ' ===')

        try:
            self.emitter.emit('error', error)
            if self.client.keep_running:
                self.client.close()
        except Exception as e:
            LOG.error('Exception closing websocket: ' + repr(e))

        LOG.warning("WS Client will reconnect in %d seconds." % self.retry)
        time.sleep(self.retry)
        self.retry = min(self.retry * 2, 60)
        try:
            self.emitter.emit('reconnecting')
            self.client = self.create_client()
            self.run_forever()
        except WebSocketException:
            pass

    def on_message(self, ws, message):
        self.emitter.emit('message', message)
        parsed_message = Message.deserialize(message)
        self.pool.apply_async(
            self.emitter.emit, (parsed_message.type, parsed_message))

    def emit(self, message):
        if not self.connected_event.wait(10):
            if not self.started_running:
                raise ValueError('You must execute run_forever() '
                                 'before emitting messages')
            self.connected_event.wait()

        try:
            if hasattr(message, 'serialize'):
                self.client.send(message.serialize())
            else:
                self.client.send(json.dumps(message.__dict__))
        except WebSocketConnectionClosedException:
            LOG.warning('Could not send {} message because connection '
                        'has been closed'.format(message.type))

    def wait_for_response(self, message, reply_type=None, timeout=None):
        """Send a message and wait for a response.

        Args:
            message (Message): message to send
            reply_type (str): the message type of the expected reply.
                              Defaults to "<message.type>.response".
            timeout: seconds to wait before timeout, defaults to 3
        Returns:
            The received message or None if the response timed out
        """
        response = []

        def handler(message):
            """Receive response data."""
            response.append(message)

        # Setup response handler
        self.once(reply_type or message.type + '.response', handler)
        # Send request
        self.emit(message)
        # Wait for response
        start_time = time.monotonic()
        while len(response) == 0:
            time.sleep(0.2)
            if time.monotonic() - start_time > (timeout or 3.0):
                try:
                    self.remove(reply_type, handler)
                except (ValueError, KeyError):
                    # ValueError occurs on pyee 1.0.1 removing handlers
                    # registered with once.
                    # KeyError may theoretically occur if the event occurs as
                    # the handler is removed
                    pass
                return None
        return response[0]

    def on(self, event_name, func):
        self.emitter.on(event_name, func)

    def once(self, event_name, func):
        self.emitter.once(event_name, func)

    def remove(self, event_name, func):
        try:
            if event_name in self.emitter._events:
                LOG.debug("Removing found '"+str(event_name)+"'")
            else:
                LOG.debug("Not able to find '"+str(event_name)+"'")
            self.emitter.remove_listener(event_name, func)
        except ValueError as e:
            LOG.warning('Failed to remove event {}: {}'.format(event_name,
                                                               str(func)))
            for line in traceback.format_stack():
                LOG.warning(line.strip())

            if event_name in self.emitter._events:
                LOG.debug("Removing found '"+str(event_name)+"'")
            else:
                LOG.debug("Not able to find '"+str(event_name)+"'")
            LOG.warning("Existing events: " + str(self.emitter._events))
            for evt in self.emitter._events:
                LOG.warning("   "+str(evt))
                LOG.warning("       "+str(self.emitter._events[evt]))
            if event_name in self.emitter._events:
                LOG.debug("Removing found '"+str(event_name)+"'")
            else:
                LOG.debug("Not able to find '"+str(event_name)+"'")
            LOG.warning('----- End dump -----')

    def remove_all_listeners(self, event_name):
        '''
            Remove all listeners connected to event_name.

            Args:
                event_name: event from which to remove listeners
        '''
        if event_name is None:
            raise ValueError
        self.emitter.remove_all_listeners(event_name)

    def run_forever(self):
        self.started_running = True
        self.client.run_forever()

    def close(self):
        self.client.close()
        self.connected_event.clear()
示例#34
0
文件: ws.py 项目: OnyxProject/Onyx
class WebsocketClient(object):
    def __init__(self, host=config.get("Websocket", "host"), port=int(config.get("Websocket", "port")),
                 route=config.get("Websocket", "route"), ssl=config.getboolean("Websocket", "ssl")):

        validate_param(host, "websocket.host")
        validate_param(port, "websocket.port")
        validate_param(route, "websocket.route")

        self.build_url(host, port, route, ssl)
        self.emitter = EventEmitter()
        self.client = self.create_client()
        self.pool = ThreadPool(10)
        self.retry = 5

    def build_url(self, host, port, route, ssl):
        scheme = "wss" if ssl else "ws"
        self.url = scheme + "://" + host + ":" + str(port) + route

    def create_client(self):
        return WebSocketApp(self.url,
                            on_open=self.on_open, on_close=self.on_close,
                            on_error=self.on_error, on_message=self.on_message)

    def on_open(self, ws):
        LOG.info("Connected")
        self.emitter.emit("open")

    def on_close(self, ws):
        self.emitter.emit("close")

    def on_error(self, ws, error):
        try:
            self.emitter.emit('error', error)
            self.client.close()
        except Exception as e:
            LOG.error(repr(e))
        LOG.warn("WS Client will reconnect in %d seconds." % self.retry)
        time.sleep(self.retry)
        self.retry = min(self.retry * 2, 60)
        self.client = self.create_client()
        self.run_forever()

    def on_message(self, ws, message):
        self.emitter.emit('message', message)
        parsed_message = Message.deserialize(message)
        self.pool.apply_async(
            self.emitter.emit, (parsed_message.type, parsed_message))

    def emit(self, message):
        if (not self.client or not self.client.sock or
                not self.client.sock.connected):
            return
        if hasattr(message, 'serialize'):
            self.client.send(message.serialize())
        else:
            self.client.send(json.dumps(message.__dict__))

    def on(self, event_name, func):
        self.emitter.on(event_name, func)

    def once(self, event_name, func):
        self.emitter.once(event_name, func)

    def remove(self, event_name, func):
        self.emitter.remove_listener(event_name, func)

    def run_forever(self):
        self.client.run_forever()

    def close(self):
        self.client.close()
示例#35
0
class WebsocketClient(object):
    def __init__(self,
                 host=config.get("host"),
                 port=config.get("port"),
                 route=config.get("route"),
                 ssl=config.get("ssl")):

        validate_param(host, "websocket.host")
        validate_param(port, "websocket.port")
        validate_param(route, "websocket.route")

        self.build_url(host, port, route, ssl)
        self.emitter = EventEmitter()
        self.client = self.create_client()
        self.pool = ThreadPool(10)
        self.retry = 5

    def build_url(self, host, port, route, ssl):
        scheme = "wss" if ssl else "ws"
        self.url = scheme + "://" + host + ":" + str(port) + route

    def create_client(self):
        return WebSocketApp(self.url,
                            on_open=self.on_open,
                            on_close=self.on_close,
                            on_error=self.on_error,
                            on_message=self.on_message)

    def on_open(self, ws):
        LOG.info("Connected")
        self.emitter.emit("open")

    def on_close(self, ws):
        self.emitter.emit("close")

    def on_error(self, ws, error):
        try:
            self.emitter.emit('error', error)
            self.client.close()
        except Exception as e:
            LOG.error(repr(e))
        LOG.warn("WS Client will reconnect in %d seconds." % self.retry)
        time.sleep(self.retry)
        self.retry = min(self.retry * 2, 60)
        self.client = self.create_client()
        self.run_forever()

    def on_message(self, ws, message):
        self.emitter.emit('message', message)
        parsed_message = Message.deserialize(message)
        self.pool.apply_async(self.emitter.emit,
                              (parsed_message.type, parsed_message))

    def emit(self, message):
        if (not self.client or not self.client.sock
                or not self.client.sock.connected):
            return
        if hasattr(message, 'serialize'):
            self.client.send(message.serialize())
        else:
            self.client.send(json.dumps(message.__dict__))

    def on(self, event_name, func):
        self.emitter.on(event_name, func)

    def once(self, event_name, func):
        self.emitter.once(event_name, func)

    def remove(self, event_name, func):
        self.emitter.remove_listener(event_name, func)

    def run_forever(self):
        self.client.run_forever()

    def close(self):
        self.client.close()
示例#36
0
文件: helper.py 项目: Tilyp/pyppeteer
def addEventListener(emitter: EventEmitter, eventName: str, handler: Callable
                     ) -> Dict[str, Any]:
    """Add handler to the emitter and return emitter/handler."""
    emitter.on(eventName, handler)
    return {'emitter': emitter, 'eventName': eventName, 'handler': handler}
示例#37
0
class TemperatureSensor(Component):
    """An abstract temperature sensor interface/base."""
    def __init__(self, clock, data, reset):
        """Initialize a new instance of TempSensor.

        :param raspy.io.gpio.Gpio clock: The GPIO pin used for the clock.
        :param raspy.io.gpio.Gpio data: The GPIO used for data.
        :param raspy.io.gpio.Gpio reset: The GPIO pin used to trigger reset.
        :raises: ArgumentNullException if any of the pins are None.
        """
        Component.__init__(self)
        if clock is None:
            raise ArgumentNullException("'clock' cannot be None.")

        if data is None:
            raise ArgumentNullException("'data' cannot be None.")

        if reset is None:
            raise ArgumentNullException("'reset' cannot be None.")

        self.__emitter = EventEmitter()
        self.__rawTemp = 0.0
        self.__scale = temp_scale.CELCIUS
        self.__tempSensor = DS1620(clock, data, reset)

    def dispose(self):
        """Release managed resources used by this component."""
        if self.is_disposed:
            return

        if self.__tempSensor is not None:
            self.__tempSensor.dispose()
            self.__tempSensor = None

        self.__rawTemp = 0.0
        self.__scale = temp_scale.CELCIUS
        self.__emitter.remove_all_listeners()
        self.__emitter = None
        Component.dispose(self)

    def on(self, evt, callback):
        """Register an event with a callback to handle it.

        :param str evt: The name of the event to register a handler for.
        :param function callback: The callback to execute when the event
        fires.
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("TempSensor")

        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Emit the specified event to all registered listeners.

        :param str evt: The name of the event to emit.
        :param object args: The arguments to pass to the event handlers
        (listeners).
        :raises: ObjectDisposedException if this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("TempSensor")

        self.__emitter.emit(evt, args)

    def remove_all_listeners(self):
        """Remove all registered event listeners."""
        if self.is_disposed:
            return

        if self.__emitter is not None:
            self.__emitter.remove_all_listeners()

    def get_raw_temperature(self):
        """Get the raw temperature value.

        :returns: The raw value read from the sensor.
        :rtype: float
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        return self.__rawTemp

    @property
    def scale(self):
        """Get the temperature scale.

        :returns: The temperature scale.
        :rtype: int
        """
        return self.__scale

    @scale.setter
    def scale(self, the_scale):
        """Set the temperature scale.

        :param int the_scale: The temperature scale to set.
        """
        self.__scale = the_scale

    def _set_raw_temp(self, temp):
        """Set the raw temperature.

        :param float temp: The temperature to set.
        """
        self.__rawTemp = temp

    def on_temperature_change(self, change_evt):
        """Fire the temperature change event.

        :param raspy.components.temperature.temp_chang_event.TempChangeEvent change_evt:
        The event object.
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("TempSensor")

        _t = threading.Thread(target=self.emit,
                              name=EVENT_TEMPERATURE_CHANGED,
                              args=(EVENT_TEMPERATURE_CHANGED, change_evt))
        _t.daemon = True
        _t.start()

    def get_temperature(self, scale):
        """Get the temperature value.

        :param int scale: The scale to use for measurement.
        :returns: The temperature value in the specified scale.
        :rtype: float
        :raises: ObjectDisposedException if this instance has been disposed.
        """
        raw = self.get_raw_temperature()
        return temp_conversion.convert(self.scale, scale, raw)

    @property
    def sensor(self):
        """Get the sensor being used to measure.

        :returns: The temperature sensor.
        :rtype: raspy.sensors.ds1620.DS1620
        """
        return self.__tempSensor
示例#38
0
class Button(Component):
    """A buttons device abstraction component base class."""

    def __init__(self):
        """Initialize a new Button."""
        super(Component, self).__init__()
        self.__holdTimer = None
        self.__baseState = button_state.RELEASED
        self.__emitter = EventEmitter()

    @property
    def is_pressed(self):
        """Get a value indicating whether or not the buttons is pressed.

        :returns: True if the buttons is pressed; Otherwise, False.
        :rtype: bool
        """
        return self.__baseState == button_state.PRESSED

    @property
    def is_released(self):
        """Get a value indicating whether or not the buttons is released.

        :returns: True if the buttons is released; Otherwise, False.
        :rtype: bool
        """
        return self.__baseState == button_state.RELEASED

    def _set_state(self, state):
        """Override state with the specified state.

        :param int state: The state to set.
        """
        self.__baseState = state

    @property
    def state(self):
        """Get the buttons state.

        :returns: The buttons state.
        :rtype: int
        """
        return self.__baseState

    def is_state(self, state):
        """Check to see if the buttons is in the specified state.

        :param int state: The state to check.
        :returns: True if the buttons is in the specified state.
        :rtype: bool
        """
        return self.__baseState == state

    def on(self, evt, callback):
        """Register an event with a callback to handle it.

        :param str evt: The name of the event to register a handler for.
        :param function callback: The callback to execute when the event
        fires.
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Button")

        self.__emitter.on(evt, callback)

    def emit(self, evt, args):
        """Emit the specified event to all registered listeners.

        :param str evt: The name of the event to emit.
        :param object args: The arguments to pass to the event handlers
        (listeners).
        :raises: raspy.object_disposed_exception.ObjectDisposedException if
        this instance is disposed.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Button")

        self.__emitter.emit(evt, args)

    def on_button_hold(self, btn_event):
        """Fire the buttons hold event.

        :param raspy.components.buttons.button_event.ButtonEvent btn_event: The
        buttons event info.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Button")

        self.emit(EVENT_HOLD, btn_event)

    def _on_hold_timer_elapsed(self, btn_event):
        """Handle the timer elapsed event.

        This internal method fires the button hold event when the hold timer
        elapses. Should only be called by _fire_button_hold_event().

        :param raspy.components.buttons.button_event.ButtonEvent btn_event: The
        button event info.
        """
        if self.is_pressed:
            self.on_button_hold(btn_event)

    def _stop_hold_timer(self):
        """Stop the internal hold timer."""
        if self.__holdTimer is not None:
            self.__holdTimer.cancel()

        self.__holdTimer = None

    def _fire_button_hold_event(self):
        """Fire the timer elapsed event handler."""
        evt = ButtonEvent(self)
        self._on_hold_timer_elapsed(evt)

    def _start_hold_timer(self):
        """Start the button hold timer."""
        self.__holdTimer = Timer(2.0, self._fire_button_hold_event)
        self.__holdTimer.start()

    def on_state_changed(self, btn_event):
        """Fire the buttons state changed event.

        :param raspy.components.buttons.button_event.ButtonEvent btn_event: The
        buttons event info.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Button")

        self.emit(EVENT_STATE_CHANGED, btn_event)
        if btn_event.is_pressed:
            self.on_button_pressed(btn_event)

        if btn_event.is_released:
            self.on_button_released(btn_event)

    def on_button_pressed(self, btn_event):
        """Fire the buttons pressed event.

        :param raspy.components.buttons.button_event.ButtonEvent btn_event: The
        buttons event info.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Button")

        self.emit(EVENT_PRESSED, btn_event)
        self._stop_hold_timer()
        self._start_hold_timer()

    def on_button_released(self, btn_event):
        """Fire the buttons released event.

        :param raspy.components.buttons.button_event.ButtonEvent btn_event: The
        buttons event info.
        """
        if self.is_disposed:
            raise ObjectDisposedException("Button")

        self.emit(EVENT_RELEASED, btn_event)
        self._stop_hold_timer()

    def __str__(self):
        """Return the string representation of this class instance.

        :returns: The string representation of this class.
        :rtype: str
        """
        base = Component.component_name.fget()
        if not string_utils.is_null_or_empty(base):
            return base
        return self.__class__.__name__

    def dispose(self):
        """Dispose of all the managed resources used by this instance."""
        if self.is_disposed:
            return

        self.__emitter.remove_all_listeners()
        self._stop_hold_timer()
        self.__emitter = None
        Component.dispose(self)