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())
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 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 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()
class Test_KasaDaemon(unittest.TestCase): 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 tearDown(self): self.m_kasaDaemon.Exit() self.m_daemon.close() self.assertEqual(self.m_kasaDaemon.ExitCode(), 0) def test_Power(self): # Since the above mock is out of scope, we must create a new mock here with mock.patch('pygrill.kasa.kasa_daemon.socket.socket') as mockitem: mock_inst = mockitem.return_value mock_inst.recv.return_value = kasa_daemon.EncryptWithHeader( TEST.KASA.DAEMON.OFF_ON_NO_ERROR_RSP) self.m_kasaDaemon.TurnPlugOn() self.assertListEqual(self.m_kasaDaemon.GetErrors(), list()) mock_inst.send.assert_called_with( kasa_daemon.EncryptWithHeader(KASA.DAEMON.JSON_PLUG_ON)) mock_inst.reset_mock() mock_inst.recv.return_value = kasa_daemon.EncryptWithHeader( TEST.KASA.DAEMON.ON_ON_NO_ERROR_RSP) self.m_kasaDaemon.TurnPlugOn() self.assertListEqual(self.m_kasaDaemon.GetErrors(), list()) mock_inst.send.assert_called_with( kasa_daemon.EncryptWithHeader(KASA.DAEMON.JSON_COUNTDOWN_DELETE_AND_RUN)) mock_inst.reset_mock() mock_inst.recv.return_value = kasa_daemon.EncryptWithHeader( TEST.KASA.DAEMON.ON_OFF_NO_ERROR_RSP) self.m_kasaDaemon.TurnPlugOff() self.assertListEqual(self.m_kasaDaemon.GetErrors(), list()) mock_inst.send.assert_called_with( kasa_daemon.EncryptWithHeader(KASA.DAEMON.JSON_PLUG_OFF)) mock_inst.reset_mock() mock_inst.recv.return_value = kasa_daemon.EncryptWithHeader( TEST.KASA.DAEMON.OFF_OFF_NO_ERROR_RSP) self.m_kasaDaemon.TurnPlugOff() self.assertListEqual(self.m_kasaDaemon.GetErrors(), list()) mock_inst.send.assert_called_with( kasa_daemon.EncryptWithHeader(KASA.DAEMON.JSON_COUNTDOWN_DELETE)) mock_inst.reset_mock() mock_inst.recv.return_value = kasa_daemon.EncryptWithHeader( TEST.KASA.DAEMON.OFF_ERROR_RSP) self.m_kasaDaemon.TurnPlugOff() mock_inst.send.assert_called_with( kasa_daemon.EncryptWithHeader(KASA.DAEMON.JSON_COUNTDOWN_DELETE)) resp = list() resp.append(kasa_daemon.Decrypt( kasa_daemon.Encrypt(TEST.KASA.DAEMON.OFF_ERROR_RSP))) resp.append(kasa_daemon.Decrypt( kasa_daemon.Encrypt(TEST.KASA.DAEMON.OFF_ERROR_RSP))) print(self.m_kasaDaemon.GetErrors()) self.assertListEqual(self.m_kasaDaemon.GetErrors(), resp) mock_inst.send.assert_called() mock_inst.reset_mock() self.assertEqual(self.m_kasaDaemon.GetActive(), False) def test_IP(self): self.assertEqual(self.m_kasaDaemon.GetIP(), "192.168.0.0")