Пример #1
0
 def new_init(self, *args, **kwargs):
     """
     Call the original ctor and then pass self to a new local protocol and append it to the broker
     """
     result = orig_init(self, *args, **kwargs)
     protocol_obj = LocalItemProtocol(self)
     Broker.get_instance().pyadapter.track_open_protocol(protocol_obj)
     self._local_protocol = protocol_obj
     return result
Пример #2
0
def delay(seconds):
    """

    :param seconds:
    :return:
    """
    d = defer.Deferred()
    Broker.get_instance().reactor.callLater(seconds, lambda: d.callback(None))
    return d
Пример #3
0
def delay(seconds):
    """

    :param seconds:
    :return:
    """
    d = defer.Deferred()
    Broker.get_instance().reactor.callLater(seconds, lambda: d.callback(None))
    return d
Пример #4
0
 def new_init(self, *args, **kwargs):
     """
     Call the original ctor and then pass self to a new local protocol and append it to the broker
     """
     result = orig_init(self, *args, **kwargs)
     protocol_obj = LocalItemProtocol(self)
     Broker.get_instance().pyadapter.track_open_protocol(protocol_obj)
     self._local_protocol = protocol_obj
     return result
Пример #5
0
def delay(seconds):
    """
    Calls the function after a certain amount of time has passed.
    :param seconds: The amount of time to wait in seconds before calling.
    :return: A deferred.
    """
    d = defer.Deferred()
    d = log_stack_on_error(d)
    Broker.get_instance().reactor.callLater(seconds, lambda: d.callback(None))
    return d
Пример #6
0
    def __init__(self, item_id, name, adapter=None):
        self.item_id = item_id
        self.item_name = name
        """:type Adapter"""  # use the default pyadapter if no specific adapter was chosen
        self._adapter = adapter if adapter is not None else Broker.get_instance().pyadapter
        self.children = []  # child items

        # subscribe on_message to be called whenever we get a message *to* us
        self.subscribe(self.on_message, TO=item_id)
        self._interfaces = []  # list of interfaces we support
Пример #7
0
 def http_request(self, path="/", encode='zlib'):
     """
     Do an http request on the broker
     :type path str
     """
     url = "http://localhost:" + str(Broker.get_instance().http_port) + path
     print url
     # http"://localhost:broker.http_port
     request = self._http_agent.request(
         'GET', url, Headers({'User-Agent': ['Twisted Web Client']}), None)
     request.addCallback(lambda response: readBody(response))
     request.addCallback(lambda html: (base64.b64encode(html.encode(encode))
                                       ) if encode == "zlib" else html)
     return request
Пример #8
0
 def http_request(self, path="/"):
     """
     Do an http request on the broker
     :type path str
     """
     url = "http://localhost:" + str(Broker.get_instance().http_port)+path
     # http"://localhost:broker.http_port
     request = self._http_agent.request(
         'GET',
         url,
         Headers({'User-Agent': ['Twisted Web Client Example']}),
         None)
     request.addCallback(lambda response: readBody(response))
     request.addCallback(lambda html: base64.b64encode(html.encode("zlib")))
     return request
Пример #9
0
    def __init__(self, default=None, val_type=None, units="", callback=lambda _: _):
        """
        Init method for ParlayDatastream class

        :param default: default value for the streaming data
        :param units: optional string indicating units, to be returned during discovery
        :param callback: a functiomn to call with the new value every time this datastream changes
        :return:
        """
        self._default_val = default
        self.listeners = {}  # dict: item instance -> { dict: requester_id -> listener}
        self.units = units
        self.broker = Broker.get_instance()
        self._vals = {}  # dict: item instance -> value
        self._val_type = val_type
        self._callback = callback
Пример #10
0
    def __init__(self, item_id, name, adapter=None, parents=None):
        self.item_id = item_id
        self.item_name = name
        """:type Adapter"""  # use the default pyadapter if no specific adapter was chosen
        self._adapter = adapter if adapter is not None else Broker.get_instance(
        ).pyadapter

        self.children = set()  # Initialize children set

        parents = set(
        ) if not parents else parents  # Create a set to represent the parents of the item
        self.parents = {parents} if not isinstance(parents, Iterable) else set(
            parents)  # Make sure parents is iterable
        self._add_self_as_child_to_parents()

        # subscribe on_message to be called whenever we get a message *to* us
        self.subscribe(self.on_message, TO=item_id)
        self._interfaces = []  # list of interfaces we support
Пример #11
0
from parlay.server.reactor import ReactorWrapper, twisted_reactor, python_thread
from parlay.server.broker import Broker


class ReactorImpl(ReactorWrapper):
    def __init__(self):
        ReactorWrapper.__init__(self, twisted_reactor)
        self._thread = python_thread.get_ident(
        )  # the current thread is the reactor thread
        self.running = True  # we're always running


_reactor_stub = ReactorImpl()
#make sure the Broker is using US as the reactor
Broker.get_instance().reactor = _reactor_stub


class ReactorMixin(object):
    """
    Inherit this class to get a self.reactor class that willa ct like a real reactor but give hooks for unit testing
    """

    reactor = _reactor_stub
Пример #12
0
    def close(cls):
        pass  # Don't need to do anything

    def __init__(self, item):
        BaseProtocol.__init__(self)
        self.items = [item]  # only 1
        self._unique_id = LocalItemProtocol.ID
        self._broker = Broker.get_instance()
        LocalItemProtocol.ID += 1

    def __str__(self):
        return "Local:" + str(self.items[0].__class__) + " # " + str(
            self._unique_id)


auto_started_items = []


def auto_start():
    """
    Auto start local items that have that flag set
    """
    for name, cls in LOCAL_ITEM_CLASSES.iteritems():
        if cls._local_item_auto_connect:
            #construct them on init and store them in the list so they don't get garbage collected
            auto_started_items.append(cls())


# call this when the Broker is up and running
Broker.call_on_start(auto_start)
Пример #13
0
 def __init__(self, item):
     BaseProtocol.__init__(self)
     self.items = [item]  # only 1
     self._unique_id = LocalItemProtocol.ID
     self._broker = Broker.get_instance()
     LocalItemProtocol.ID += 1
Пример #14
0
 def setUp(self):
     self._broker = Broker.get_instance()
Пример #15
0
DEFAULT_TIMEOUT = 120


# list of deferreds to cancel when cleaning up
CLEANUP_DEFERRED = set()


def cleanup():
    for d in CLEANUP_DEFERRED:
        if not d.called:
            d.cancel()


# cleanup our deferreds
Broker.call_on_stop(cleanup)


class ListenerStatus(object):
    """
    Enum object for keeping or removing listeners
    """
    KEEP_LISTENER = False
    REMOVE_LISTENER = True


class ThreadedItem(BaseItem):
    """Base object for all Parlay scripts"""
    # a list of functions that will be alerted when a new script instance is created
    stop_reactor_on_close = True
Пример #16
0
    @classmethod
    def close(cls):
        pass  # Don't need to do anything

    def __init__(self, item):
        BaseProtocol.__init__(self)
        self.items = [item]  # only 1
        self._unique_id = LocalItemProtocol.ID
        self._broker = Broker.get_instance()
        LocalItemProtocol.ID += 1

    def __str__(self):
        return "Local:" + str(self.items[0].__class__) + " # " + str(self._unique_id)


auto_started_items = []


def auto_start():
    """
    Auto start local items that have that flag set
    """
    for name, cls in LOCAL_ITEM_CLASSES.iteritems():
        if cls._local_item_auto_connect:
            # construct them on init and store them in the list so they don't get garbage collected
            auto_started_items.append(cls())


# call this when the Broker is up and running
Broker.call_on_start(auto_start)
Пример #17
0
class WebSocketServerAdapter(WebSocketServerProtocol, Adapter):
    """
    When a client connects over a websocket, this is the protocol that will handle the communication.
    The messages are encoded as a JSON string
    """

    broker = Broker.get_instance()

    def __init__(self, broker=None):
        WebSocketServerProtocol.__init__(self)
        self._discovery_response_defer = None
        self._protocol_response_defer = None
        self._open_protocol_response_defer = None

    def onClose(self, wasClean, code, reason):
        print("Closing:" + str(self))
        # clean up after ourselves
        self.broker.adapters.remove(self)

    def send_message_as_JSON(self, msg):
        """
        Send a message dictionary as JSON
        """
        self.sendMessage(json.dumps(msg))

    def onMessage(self, payload, isBinary):
        if not isBinary:
            msg = json.loads(payload)

            # if we're waiting for discovery and its a discovery response
            if self._discovery_response_defer is not None and \
                    msg['TOPICS'].get('type', None) == 'get_protocol_discovery_response':
                # discovery!
                # get skeleton
                discovery = msg['CONTENTS'].get('discovery', [])
                self._discovery_response_defer.callback(discovery)
                self._discovery_response_defer = None
            # if we're waiting for a protocol list and its a protocol response
            elif self._protocol_response_defer is not None and \
                    msg['TOPICS'].get('type', None) == 'get_protocol_list_response':

                protocol_list = msg['CONTENTS'].get('protocol_list', [])
                self._protocol_response_defer.callback(protocol_list)
                self._protocol_response_defer = None

            # else its just a regular message, publish it.
            else:
                self.broker.publish(msg, self.send_message_as_JSON)

        else:
            print("Binary messages not supported")

    def onConnect(self, request):
        # let the broker know we exist!
        self.broker.adapters.append(self)

    def discover(self, force):
        # already in the middle of discovery
        if self._discovery_response_defer is not None:
            return self._discovery_response_defer

        self._discovery_response_defer = defer.Deferred()
        self.send_message_as_JSON({
            'TOPICS': {
                'type': 'get_protocol_discovery'
            },
            'CONTENTS': {}
        })

        def timeout():
            if self._discovery_response_defer is not None:
                # call back with nothing if timeout
                self._discovery_response_defer.callback({})
                self._discovery_response_defer = None

        self.broker.reactor.callLater(10, timeout)

        return self._discovery_response_defer

    def get_protocols(self):
        """
        Return a list of protocols that could potentially be opened.
        Return a deferred if this is not ready yet
        """
        # already in the middle of discovery
        if self._protocol_response_defer is not None:
            return self._protocol_response_defer

        self._protocol_response_defer = defer.Deferred()
        self.send_message_as_JSON({
            'TOPICS': {
                'type': 'get_protocol_list'
            },
            'CONTENTS': {}
        })

        def timeout():
            if self._protocol_response_defer is not None:
                # call back with nothing if timeout
                self._protocol_response_defer.callback({})
                self._protocol_response_defer = None

        self.broker.reactor.callLater(2, timeout)

        return self._protocol_response_defer

    def get_open_protocols(self):
        return []

    def __str__(self):
        return "Websocket at " + str(self.peer)
Пример #18
0
class LineTransportServerAdapter(Adapter, LineReceiver):
    """
    Adapter class to connect the Parlay broker to a device (for example, serial)
    that implements the L{ITransport} interface.
    """

    broker = Broker.get_instance()
    DEFAULT_DISCOVERY_TIMEOUT_TIME = 3

    def __init__(self, transport_factory, delimiter='\n', **kwargs):
        """
        Creates an instance of ParlayOverLineTransportServerAdapter
        :param transport_factory: Transport class that must implement FileDescriptor interface
        :param delimiter: delimiter character that separates lines (default=newline)
        :param kwargs: optional keyword arguments to pass to transport_factory
        :return:
        """
        self._discovery_response_defer = None
        self.reactor = self.broker.reactor
        self.delimiter = str(delimiter).decode("string_escape")
        self.transport = transport_factory(self, **kwargs)
        self._cached_discovery = None
        self.discovery_timeout_time = self.DEFAULT_DISCOVERY_TIMEOUT_TIME
        Adapter.__init__(self)

    def get_protocols(self):
        return []

    def get_open_protocols(self):
        return []

    def lineReceived(self, line):
        """
        Handle a delimited line of bytes received by the transport.
        :param line:
        :return: None
        """
        msg = json.loads(line)

        # if we're waiting for discovery and the message is a discovery response
        if self._discovery_response_defer is not None and \
                msg['TOPICS'].get('type', None) == 'get_protocol_discovery_response':
            discovery = msg['CONTENTS'].get('discovery', [])
            self._cached_discovery = discovery
            self._discovery_response_defer.callback(discovery)
            self._discovery_response_defer = None

        # else it's just a regular message, publish it
        else:
            self.broker.publish(msg, self.send_message_as_json)

    def discover(self, force):
        """
        Sends a Parlay message of 'get_protocol_discovery' type via the transport.
        :param force: if False, return cached discovery if available.
        :type force: bool
        :return: Deferred to wait for discovery response
        """

        # if already in the middle of discovery
        if self._discovery_response_defer is not None:
            return self._discovery_response_defer

        if not force and self._cached_discovery is not None:
            return self._cached_discovery

        self._discovery_response_defer = defer.Deferred()
        self.send_message_as_json({
            'TOPICS': {
                'type': 'get_protocol_discovery'
            },
            'CONTENTS': {}
        })

        def timeout():
            if self._discovery_response_defer is not None:
                # call back with nothing if timeout
                self._discovery_response_defer.callback({})
                self._discovery_response_defer = None

        self.reactor.callLater(self.discovery_timeout_time, timeout)
        return self._discovery_response_defer

    def send_message_as_json(self, msg):
        """
        Transforms parlay message dictionary to JSON, adds delimiting character,
        and sends it over the transport.
        :param msg:
        :return:
        """
        self.sendLine(json.dumps(msg))
Пример #19
0
 def __init__(self, item):
     BaseProtocol.__init__(self)
     self.items = [item]  # only 1
     self._unique_id = LocalItemProtocol.ID
     self._broker = Broker.get_instance()
     LocalItemProtocol.ID += 1
Пример #20
0
 def __init__(self):
     self._broker = Broker.get_instance()
Пример #21
0
# a list of Item proxy classes for Scripts
ITEM_PROXIES = {}

# list of deferreds to cancel when cleaning up
CLEANUP_DEFERRED = set()


def cleanup():
    for d in CLEANUP_DEFERRED:
        if not d.called:
            d.cancel()


# cleanup our deferreds
Broker.call_on_stop(cleanup)


class ListenerStatus(object):
    """
    Enum object for keeping or removing listeners
    """
    KEEP_LISTENER = False
    REMOVE_LISTENER = True


class ThreadedItem(BaseItem):
    """Base object for all Parlay scripts"""
    # a list of functions that will be alerted when a new script instance is created
    stop_reactor_on_close = True
Пример #22
0
 def __init__(self):
     self._broker = Broker.get_instance()
Пример #23
0
 def __init__(self, adapter=None):
     WebSocketClientProtocol.__init__(self)
     self._adapter = adapter if adapter is not None else Broker.get_instance(
     ).pyadapter
Пример #24
0
 def open_for_obj(cls, item_obj):
     protocol_obj = LocalItemProtocol(item_obj)
     Broker.get_instance().pyadapter.track_open_protocol(protocol_obj)
     return protocol_obj
Пример #25
0
 def open_for_obj(cls, item_obj):
     protocol_obj = LocalItemProtocol(item_obj)
     Broker.get_instance().pyadapter.track_open_protocol(protocol_obj)
     return protocol_obj
Пример #26
0
class ASCIILineProtocol(BaseProtocol, LineReceiver):
    """
    When a client connects over a serial, this is the protocol that will handle the communication.
    The messages are encoded as a JSON string
    """

    broker = Broker.get_instance()
    open_ports = set()

    def __init__(self, port):
        self._parlay_name = port
        if not hasattr(self, "items"):
            self.items = [LineItem(self._parlay_name, self._parlay_name, self)]
        BaseProtocol.__init__(self)

    @classmethod
    def open(cls,
             broker,
             port="/dev/tty.usbserial-FTAJOUB2",
             baudrate=57600,
             delimiter="\n"):
        """
        This will be called bvy the system to construct and open a new SSCOM_Serial protocol
        :param cls : The class object (supplied by system)
        :param broker:  current broker insatnce (supplied by system)
        :param port: the serial port device to use. On linux, something like "/dev/ttyUSB0". On windows something like "COM0"
        :param baudrate: baudrate of serial connection
        :param delimiter:
        """
        if isinstance(port, list):
            port = port[0]

        p = cls(port)
        cls.delimiter = str(delimiter).decode("string_escape")

        SerialPort(p, port, broker.reactor, baudrate=baudrate)

        return p

    @classmethod
    def get_open_params_defaults(cls):
        """Override base class function to show dropdowns for defaults"""
        from serial.tools import list_ports

        defaults = BaseProtocol.get_open_params_defaults()

        potential_serials = [x[0] for x in list_ports.comports()]
        defaults['port'] = potential_serials
        defaults['baudrate'] = [
            300, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600,
            115200, 230400
        ]
        defaults['delimiter'] = "\n"

        return defaults

    def close(self):
        self.transport.loseConnection()
        return defer.succeed(
            None
        )  # fake deferred since we don't have anything asynchronous to do

    def lineReceived(self, line):
        for item in self.items:
            item.LAST_LINE_RECEIVED = line

        # send to all children who are waiting for it
        self.got_new_data(line)

    def rawDataReceived(self, data):
        self.got_new_data(data)

    def __str__(self):
        return "Serial Terminal @ " + self._parlay_name
Пример #27
0
 def setUp(self):
     self._broker = Broker.get_instance()
Пример #28
0
from parlay.server.reactor import ReactorWrapper, twisted_reactor, python_thread
from parlay.server.broker import Broker

class ReactorImpl(ReactorWrapper):

    def __init__(self):
        ReactorWrapper.__init__(self, twisted_reactor)
        self._thread = python_thread.get_ident()  # the current thread is the reactor thread
        self.running = True  # we're always running




_reactor_stub = ReactorImpl()
#make sure the Broker is using US as the reactor
Broker.get_instance().reactor = _reactor_stub

class ReactorMixin(object):
    """
    Inherit this class to get a self.reactor class that willa ct like a real reactor but give hooks for unit testing
    """

    reactor = _reactor_stub