class Test_BuzzerDaemon(unittest.TestCase): def setUp(self): self.m_daemon = Daemon(host=BUZZ.DAEMON.PYRO_HOST, port=BUZZ.DAEMON.PYRO_PORT) with mock.patch('pygrill.board.buzzer_daemon.pigpio.pi') as mockitem: self.m_mock_inst = mockitem.return_value self.m_buzzDaemon = buzzer_daemon.Buzzer(self.m_daemon, boardIn=SSRC.BOARD.REV_sD) self.m_daemon.register(self.m_buzzDaemon, objectId=BUZZ.DAEMON.PYRO_OBJECT_ID) def tearDown(self): self.m_buzzDaemon.Exit() self.m_daemon.close() self.assertEqual(self.m_buzzDaemon.ExitCode(), 0) def test_buzzer(self): buzzDaemon = self.m_buzzDaemon mock_inst = self.m_mock_inst pin = SSRC.BOARD.ITEMS["Buzzer"][SSRC.BOARD.REV_sD][SSRC.BOARD.ITEM_IO] mock_inst.hardware_PWM.assert_called_with(pin, 2000, 0) buzzDaemon.Done() mock_inst.reset_mock() time.sleep(0.6) mock_inst.hardware_PWM.assert_any_call(pin, 2500, 500000) mock_inst.hardware_PWM.assert_any_call(pin, 2500, 0) buzzDaemon.LowBattery() mock_inst.reset_mock() time.sleep(0.6) mock_inst.hardware_PWM.assert_any_call(pin, 3000, 500000) mock_inst.hardware_PWM.assert_any_call(pin, 2000, 500000) buzzDaemon.Stop() mock_inst.reset_mock() time.sleep(0.1) mock_inst.hardware_PWM.assert_called_with(pin, 2000, 0)
def setUp(self): self.m_daemon = Daemon(host=BUZZ.DAEMON.PYRO_HOST, port=BUZZ.DAEMON.PYRO_PORT) with mock.patch('pygrill.board.buzzer_daemon.pigpio.pi') as mockitem: self.m_mock_inst = mockitem.return_value self.m_buzzDaemon = buzzer_daemon.Buzzer(self.m_daemon, boardIn=SSRC.BOARD.REV_sD) self.m_daemon.register(self.m_buzzDaemon, objectId=BUZZ.DAEMON.PYRO_OBJECT_ID)
def main(): config = configparser.ConfigParser() # does not throw an error, just returns the empty set if the file doesn't exist config.read(CONFIG.BASEPATH + '/config/iGrill_config.ini') loglevel = config.get("Logging", "LogLevel", fallback="Error") logfile = config.get("Logging", "LogFile", fallback="") parser = argparse.ArgumentParser( description='Runs a thread to control the buzzer') parser.add_argument('-l', '--log-level', action='store', dest='log_level', default=loglevel, help='Set log level, default: \'' + loglevel + '\'') parser.add_argument('-d', '--log-destination', action='store', dest='log_destination', default=logfile, help='Set log destination (file), default: \'' + logfile + '\'') options = parser.parse_args() SetupLog(options.log_level, options.log_destination) daemon = Daemon(host=BUZZ.DAEMON.PYRO_HOST, port=BUZZ.DAEMON.PYRO_PORT) buzzObj = Buzzer(daemon) uri = daemon.register(buzzObj, objectId=BUZZ.DAEMON.PYRO_OBJECT_ID) logging.debug(uri) daemon.requestLoop() logging.debug('exited requestLoop') daemon.shutdown() daemon.close() logging.debug('daemon closed') sys.exit(buzzObj.ExitCode())
def run_maestral_daemon(config_name="maestral", run=True, log_to_stdout=False): """ Wraps :class:`maestral.main.Maestral` as Pyro daemon object, creates a new instance and start Pyro's event loop to listen for requests on a unix domain socket. This call will block until the event loop shuts down. This command will return silently if the daemon is already running. :param str config_name: The name of the Maestral configuration to use. :param bool run: If ``True``, start syncing automatically. Defaults to ``True``. :param bool log_to_stdout: If ``True``, write logs to stdout. Defaults to ``False``. """ from maestral.main import Maestral sock_name = sockpath_for_config(config_name) pid_name = pidpath_for_config(config_name) lockfile = PIDLockFile(pid_name) # acquire PID lock file try: lockfile.acquire(timeout=1) except AlreadyLocked: if is_pidfile_stale(lockfile): lockfile.break_lock() else: logger.debug(f"Maestral already running") return logger.debug(f"Starting Maestral daemon on socket '{sock_name}'") try: # clean up old socket, create new one try: os.remove(sock_name) except FileNotFoundError: pass daemon = Daemon(unixsocket=sock_name) # start Maestral as Pyro server ExposedMaestral = expose(Maestral) # mark stop_sync and shutdown_daemon as oneway methods # so that they don't block on call ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.shutdown_pyro_daemon = oneway( ExposedMaestral.shutdown_pyro_daemon) m = ExposedMaestral(config_name, run=run, log_to_stdout=log_to_stdout) daemon.register(m, f"maestral.{config_name}") daemon.requestLoop(loopCondition=m._loop_condition) daemon.close() except Exception: traceback.print_exc() finally: # remove PID lock lockfile.release()
def setUp(self): self.m_daemon = Daemon(host=KASA.DAEMON.PYRO_HOST, port=KASA.DAEMON.PYRO_PORT) # This must be scoped oddly. Daemon uses sockets so we don't want to mock the socket # object untill the daemon is setup. with mock.patch('pygrill.kasa.kasa_daemon.socket.socket') as mockitem: self.m_mock_inst = mockitem.return_value self.m_mock_inst.recvfrom.return_value = [kasa_daemon.Encrypt( TEST.KASA.DAEMON.DISCOVER_RSP), ['192.168.0.0', 9999]] self.m_mock_inst.recv.return_value = kasa_daemon.EncryptWithHeader( TEST.KASA.DAEMON.DISCOVER_RSP) self.m_kasaDaemon = kasa_daemon.Kasa(self.m_daemon) self.m_daemon.register( self.m_kasaDaemon, objectId=KASA.DAEMON.PYRO_OBJECT_ID)
def main(): gui = PyroGUI() # create a pyro daemon with object daemon = Daemon() obj = MessagePrinter(gui) uri = daemon.register(obj, "pyrogui.message") gui.add_message("Pyro server started. Not using threads.") gui.add_message("Use the command line client to send messages.") urimsg = "Pyro object uri = {0}".format(uri) gui.add_message(urimsg) print(urimsg) # add a Pyro event callback to the gui's mainloop gui.install_pyro_event_callback(daemon) # enter the mainloop gui.mainloop()
def main(args): if len(args) != 3: print("usage: client.py <robotname> <robottype>") print(" type is one of: %s" % list(observers.keys())) return name = args[1] observertype = args[2] with Daemon() as daemon: observer = observers[observertype]() daemon.register(observer) gameserver = Proxy("PYRONAME:example.robotserver") robot = gameserver.register(name, observer) with robot: # make sure it disconnects, before the daemon thread uses it later robot.emote("Hi there! I'm here to kick your ass") observer.robot = robot print("Pyro server registered on %s" % daemon.locationStr) daemon.requestLoop()
def threadExecuteOrder(order, homeBroker): global option, running, ordemFinalizada with Daemon() as daemon1: homeBroker._pyroClaimOwnership() callback = CallbackHandler() daemon1.register(callback) worker = homeBroker.createWorker( callback) #Cria worker no servidor para tentar executar a ordem worker.tryExecuteOrder(order) print("Ordem enviada com sucesso!") ordemFinalizada = 1 daemon1.requestLoop( loopCondition=lambda: CallbackHandler.workdone != True) CallbackHandler.workdone = False
def threadAlert(stock, homeBroker): global option, running, ordemFinalizada with Daemon() as daemon2: homeBroker._pyroClaimOwnership() callback = CallbackHandler() daemon2.register(callback) worker = homeBroker.createWorker( callback) #Cria worker no servidor para verificar preço da ação worker.addStockToAlert(stock) print("Alerta criado com sucesso!") ordemFinalizada = 1 daemon2.requestLoop( loopCondition=lambda: CallbackHandler.workdone != True) CallbackHandler.workdone = False
def testSerializePyroTypes(self): uri = URI("PYRO:obj@host:9999") ser = self.serializer.dumps(uri) uri2 = self.serializer.loads(ser) assert isinstance(uri2, URI) assert uri2 == uri proxy = Proxy("PYRO:obj@host:9999") proxy._pyroHandshake = "handshake" ser = self.serializer.dumps(proxy) proxy2 = self.serializer.loads(ser) assert isinstance(proxy2, Proxy) assert proxy2 == proxy assert proxy2._pyroHandshake == "handshake" with Daemon(host="localhost", port=12345, nathost="localhost", natport=9876) as daemon: ser = self.serializer.dumps(daemon) daemon2 = self.serializer.loads(ser) assert isinstance(daemon2, Daemon)
help="hostname to bind server on") parser.add_option("-p", "--port", dest="port", type="int", default=0, help="port to bind server on (0=random)") parser.add_option("-u", "--unixsocket", help="Unix domain socket name to bind server on") parser.add_option("-s", "--storage", dest="storage", type="choice", choices=["sqlite", "memory"], default="sqlite", help="storage type (default=%default)") options, args = parser.parse_args() make_messagebus.storagetype = options.storage daemon = Daemon(host=options.host, port=options.port, unixsocket=options.unixsocket) uri = daemon.register(MessageBus) print("Pyro Message Bus.") print(" uri =", uri) ns = locate_ns() ns.register(PYRO_MSGBUS_NAME, uri) print(" name =", PYRO_MSGBUS_NAME) print("Server running, storage is {}.".format(make_messagebus.storagetype)) daemon.requestLoop()
def run_maestral_daemon(config_name='maestral', run=True, log_to_stdout=False): """ Wraps :class:`maestral.main.Maestral` as Pyro daemon object, creates a new instance and start Pyro's event loop to listen for requests on a unix domain socket. This call will block until the event loop shuts down. This command will return silently if the daemon is already running. :param str config_name: The name of the Maestral configuration to use. :param bool run: If ``True``, start syncing automatically. Defaults to ``True``. :param bool log_to_stdout: If ``True``, write logs to stdout. Defaults to ``False``. """ import threading from maestral.main import Maestral sock_name = sockpath_for_config(config_name) pid_name = pidpath_for_config(config_name) lockfile = PIDLockFile(pid_name) if threading.current_thread() is threading.main_thread(): signal.signal(signal.SIGTERM, _sigterm_handler) # acquire PID lock file try: lockfile.acquire(timeout=1) except (AlreadyLocked, LockTimeout): if is_pidfile_stale(lockfile): lockfile.break_lock() else: logger.debug(f'Maestral already running') return # Nice ourselves give other processes priority. We will likely only # have significant CPU usage in case of many concurrent downloads. os.nice(10) logger.debug(f'Starting Maestral daemon on socket "{sock_name}"') try: # clean up old socket try: os.remove(sock_name) except FileNotFoundError: pass daemon = Daemon(unixsocket=sock_name) # start Maestral as Pyro server ExposedMaestral = expose(Maestral) # mark stop_sync and shutdown_daemon as one way # methods so that they don't block on call ExposedMaestral.stop_sync = oneway(ExposedMaestral.stop_sync) ExposedMaestral.pause_sync = oneway(ExposedMaestral.pause_sync) ExposedMaestral.shutdown_pyro_daemon = oneway( ExposedMaestral.shutdown_pyro_daemon) m = ExposedMaestral(config_name, run=run, log_to_stdout=log_to_stdout) daemon.register(m, f'maestral.{config_name}') daemon.requestLoop(loopCondition=m._loop_condition) daemon.close() except Exception: traceback.print_exc() except (KeyboardInterrupt, SystemExit): logger.info('Received system exit') sys.exit(0) finally: lockfile.release()
# for 'Thingy' we register both serialization and deserialization hooks SerializerBase.register_dict_to_class("waheeee-custom-thingy", thingy_dict_to_class) SerializerBase.register_class_to_dict(mycustomclasses.Thingy, thingy_class_to_dict) # for 'OtherThingy' we only register a deserialization hook (and for serialization depend on serpent's default behavior) SerializerBase.register_dict_to_class("mycustomclasses.OtherThingy", otherthingy_dict_to_class) # regular Pyro server stuff @expose class Server(object): def method(self, arg): print("\nmethod called, arg=", arg) response = mycustomclasses.Thingy(999) return response def othermethod(self, arg): print("\nothermethod called, arg=", arg) response = mycustomclasses.OtherThingy(999) return response Daemon.serveSimple( { Server: "example.customclasses" }, ns=False)
import logging from Pyro5.api import expose, Daemon import Pyro5.config logging.basicConfig(level=logging.DEBUG) logging.getLogger("Pyro5").setLevel(logging.DEBUG) Pyro5.config.COMMTIMEOUT = 5.0 Pyro5.config.POLLTIMEOUT = 5.0 # only used for multiplexing server class TestDisconnect(object): @expose def echo(self, arg): print("echo: ", arg) return arg Daemon.serveSimple({TestDisconnect: "example.disconnect"}, ns=False)
from Pyro5.api import Daemon, serve import excep def my_error_handler(daemon, client_sock, method, vargs, kwargs, exception): print("\nERROR IN METHOD CALL USER CODE:") print(" client={} method={} exception={}".format(client_sock, method.__qualname__, repr(exception))) daemon = Daemon() daemon.methodcall_error_handler = my_error_handler serve({excep.TestClass: "example.exceptions"}, daemon=daemon, use_ns=True, verbose=True)
from Pyro5.api import behavior, expose, locate_ns, Daemon import Pyro5.config from diffiehellman import DiffieHellman Pyro5.config.SERVERTYPE = "multiplex" ns = locate_ns() @behavior(instance_mode="session") class KeyExchange(object): def __init__(self): print("New KeyExchange, initializing Diffie-Hellman") self.dh = DiffieHellman(group=14) @expose def exchange_key(self, other_public_key): print("received a public key, calculating shared secret...") self.dh.make_shared_secret_and_key(other_public_key) print("shared secret key = ", self.dh.key) return self.dh.public_key Daemon.serveSimple({KeyExchange: "example.dh.keyexchange"}, ns=True)
from Pyro5.api import expose, Daemon fmt = '%Y-%m-%d %H:%M:%S %Z%z' @expose class Server(object): def echo(self, date): print("ECHO:") print(" [raw] ", repr(date)) if hasattr(date, "isoformat"): print(" [iso] ", date.isoformat()) return date def pytz(self): tz_nl = pytz.timezone("Europe/Amsterdam") return tz_nl.localize(datetime.datetime.now()) def dateutil(self): tz_nl = dateutil.tz.gettz("Europe/Amsterdam") return datetime.datetime.now(tz_nl) def pendulum(self): tz_nl = pendulum.now("Europe/Amsterdam") return tz_nl # main program Daemon.serveSimple({Server: "example.timezones"}, ns=False)
import os from Pyro5.api import expose, Daemon @expose class Thingy(object): def message(self, arg): print("Message received:", arg) return "Roger!" if os.path.exists("example_unix.sock"): os.remove("example_unix.sock") with Daemon(unixsocket="example_unix.sock") as d: uri = d.register(Thingy, "example.unixsock") print("Server running, uri=", uri) d.requestLoop()
from Pyro5.api import expose, Daemon, config @expose class CalcServer(object): def add(self, num1, num2): print("calling add: %d, %d" % (num1, num2)) return num1 + num2 config.COMMTIMEOUT = 0.5 # the server should time out easily now Daemon.serveSimple({CalcServer: "example.autoretry"})
import time from Pyro5.api import expose, Daemon print("Autoreconnect using PYRO uri.") @expose class TestClass(object): def method(self, arg): print("Method called with %s" % arg) print("You can now try to stop this server with ctrl-C/ctrl-Break") time.sleep(1) # We are responsible to (re)connect objects with the same object Id, # so that the client can reuse its PYRO-uri directly to reconnect. # There are a few options, such as depending on the Name server to # maintain a name registration for our object (see the serverNS for this). # Or we could store our objects in our own persistent database. # But for this example we will just use a pre-generated id (fixed name). # The other thing is that your Daemon must re-bind on the same port. # By default Pyro will select a random port so we specify a fixed port. with Daemon(port=7777) as daemon: uri = daemon.register(TestClass, objectId="example.autoreconnect_fixed_objectid") print("Server started, uri: %s" % uri) daemon.requestLoop()
import time import threading from Pyro5.api import expose, oneway, behavior, Daemon @expose @behavior("single") class Server(object): def __init__(self): self.counter = 0 @oneway def increment_oneway(self): print("oneway call executing in thread", threading.get_ident()) time.sleep(0.5) self.counter += 1 def increment(self): time.sleep(0.5) self.counter += 1 def getcount(self): return self.counter print("main thread:", threading.get_ident()) Daemon.serveSimple({Server: "example.oneway2"})
from Pyro5.api import locate_ns, Daemon, type_meta, Proxy from resources import LaserPrinter, MatrixPrinter, PhotoPrinter, TapeStorage, DiskStorage, Telephone, Faxmachine # register various objects with some metadata describing their resource class ns = locate_ns() d = Daemon() uri = d.register(LaserPrinter) ns.register("example.resource.laserprinter", uri, metadata=type_meta(LaserPrinter) | {"resource:printer", "performance:fast"}) uri = d.register(MatrixPrinter) ns.register("example.resource.matrixprinter", uri, metadata=type_meta(MatrixPrinter) | {"resource:printer", "performance:slow"}) uri = d.register(PhotoPrinter) ns.register("example.resource.photoprinter", uri, metadata=type_meta(PhotoPrinter) | {"resource:printer", "performance:slow"}) uri = d.register(TapeStorage) ns.register("example.resource.tapestorage", uri, metadata=type_meta(TapeStorage) | {"resource:storage", "performance:slow"}) uri = d.register(DiskStorage) ns.register("example.resource.diskstorage", uri, metadata=type_meta(DiskStorage)
import os from Pyro5.api import expose, Daemon class QuoteGen(object): @expose def quote(self): try: quote = os.popen('fortune').read() if len(quote) > 0: return quote return "This system cannot provide you a good fortune, install 'fortune'" except: return "This system knows no witty quotes :-(" with Daemon() as daemon: quote1 = QuoteGen() quote2 = QuoteGen() uri1 = daemon.register(quote1) # let Pyro create a unique name for this one uri2 = daemon.register(quote2, "example.quotegen") # provide a logical name ourselves print("QuoteGen is ready, not using the Name Server.") print("You can use the following two URIs to connect to me:") print(uri1) print(uri2) daemon.requestLoop()
class SessionInstance(object): @expose def msg(self, message): print("[%s] %s.msg: %s" % (id(self), self.__class__.__name__, message)) return id(self), self.correlation_id @classmethod def create_instance(cls): obj = cls() obj.correlation_id = current_context.correlation_id return obj @behavior(instance_mode="percall") class PercallInstance(object): @expose def msg(self, message): print("[%s] %s.msg: %s" % (id(self), self.__class__.__name__, message)) return id(self) if __name__ == "__main__": # please make sure a name server is running somewhere first. Daemon.serveSimple( { SingleInstance: "instance.single", SessionInstance: "instance.session", PercallInstance: "instance.percall" }, verbose=True)
self.resultqueue = queue.Queue() def putWork(self, item): self.workqueue.put(item) def getWork(self, timeout=5): try: return self.workqueue.get(block=True, timeout=timeout) except queue.Empty: raise ValueError("no items in queue") def putResult(self, item): self.resultqueue.put(item) def getResult(self, timeout=5): try: return self.resultqueue.get(block=True, timeout=timeout) except queue.Empty: raise ValueError("no result available") def workQueueSize(self): return self.workqueue.qsize() def resultQueueSize(self): return self.resultqueue.qsize() # main program Daemon.serveSimple({DispatcherQueue: "example.distributed.dispatcher"})
self.number = number self.callback = callback print("Worker %d created" % self.number) @expose @oneway def work(self, amount): print("Worker %d busy..." % self.number) time.sleep(amount) print("Worker %d done. Informing callback client." % self.number) self._pyroDaemon.unregister(self) self.callback._pyroClaimOwnership( ) # because this method may run in a different thread every time it's called self.callback.done(self.number) # invoke the callback object class CallbackServer(object): def __init__(self): self.number = 0 @expose def addworker(self, callback): self.number += 1 print("server: adding worker %d" % self.number) worker = Worker(self.number, callback) self._pyroDaemon.register(worker) # make it a Pyro object return worker Daemon.serveSimple({CallbackServer: "example.callback"})
import time from Pyro5.api import expose, locate_ns, Daemon, config @expose class TimeoutServer(object): def delay(self, amount): print("sleeping %d" % amount) time.sleep(amount) print("done.") return "slept %d seconds" % amount config.COMMTIMEOUT = 0 # the server won't be using timeouts ns = locate_ns() daemon = Daemon() daemon2 = Daemon() obj = TimeoutServer() obj2 = TimeoutServer() uri = daemon.register(obj) uri2 = daemon2.register(obj2) ns.register("example.timeout", uri) ns.register("example.timeout.frozendaemon", uri2) print("Server ready.") # Note that we're only starting one of the 2 daemons. # daemon2 is not started, to simulate connection timeouts. daemon.requestLoop()
#!/usr/bin/env python3 """Daemon.""" from Pyro5.api import Daemon, expose, behavior, serve, current_context, oneway from gpio_led import LEDPanel @expose @behavior(instance_mode="single") class Photobooth(object): """Photobooth daemon.""" def __init__(self): self.ledPanelCtl = None @oneway def ledCtl(self, action, resume, brightness, kwargs): if not self.ledPanelCtl: self.ledPanelCtl = LEDPanel().get_effects() self.ledPanelCtl.abort() self.ledPanelCtl.run(action, resume, brightness, kwargs) if __name__ == "__main__": daemon = Daemon(host="localhost", port=9090) uri = daemon.register(Photobooth, 'ledpanel.control') daemon.requestLoop()
import Pyro5.config # Pyro5.config.COMMTIMEOUT=2 class Testclass(object): @expose def transfer(self, data): if Pyro5.config.SERIALIZER == "serpent" and type(data) is dict: data = serpent.tobytes(data) # in case of serpent encoded bytes print("received %d bytes" % len(data)) return len(data) @expose def download_chunks(self, size): print("client requests a 'streaming' download of %d bytes" % size) data = bytearray(size) i = 0 chunksize = 200000 print(" using chunks of size", chunksize) while i < size: yield data[i:i + chunksize] i += chunksize Daemon.serveSimple({Testclass: "example.hugetransfer"}, host=Pyro5.socketutil.get_ip_address("localhost", workaround127=True), ns=False, verbose=True)
@behavior(instance_mode="session") @expose class SessionboundDatabase(object): """ This pyro object will work fine when used from multiple proxies at the same time because you'll get a new instance for every new session (proxy connection) """ def __init__(self): # get the user-token from the USER annotation user_annotation = current_context.annotations["USER"] user = bytes(user_annotation).decode("utf-8") self.connection = database.connect(user) print("[%s] new instance and connection for user: %s" % (self.__class__.__name__, user)) def store(self, key, value): self.connection.store(key, value) def retrieve(self, key): return self.connection.retrieve(key) def ping(self): return "hi" Daemon.serveSimple({ SingletonDatabase: "example.usersession.singletondb", SessionboundDatabase: "example.usersession.sessiondb" })