def delay(seconds): """ :param seconds: :return: """ d = defer.Deferred() Broker.get_instance().reactor.callLater(seconds, lambda: d.callback(None)) return d
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
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
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
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
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
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
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
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))
def open_for_obj(cls, item_obj): protocol_obj = LocalItemProtocol(item_obj) Broker.get_instance().pyadapter.track_open_protocol(protocol_obj) return protocol_obj
def __init__(self): self._broker = Broker.get_instance()
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
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)
def setUp(self): self._broker = Broker.get_instance()
def __init__(self, adapter=None): WebSocketClientProtocol.__init__(self) self._adapter = adapter if adapter is not None else Broker.get_instance( ).pyadapter
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
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
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