Example #1
0
    def __load_settings(self):
        self.__config = Configuration(config_file_path=self.__config_file_path,
                                      allow_no_value=True)

        # get [MAIN] options
        self.__conf_hardware = self.__config.get(Config.MAIN.Hardware)
        self.__conf_display_width = self.__config.get(Config.MAIN.DisplayWidth)
        self.__conf_display_height = self.__config.get(
            Config.MAIN.DisplayHeight)
        self.__day_brightness = self.__config.get(Config.MAIN.DayBrightness)
        self.__night_brightness = self.__config.get(
            Config.MAIN.NightBrightness)
Example #2
0
    def test_something(self):
        self.driver = Configuration.create_chrome_driver()
        self.driver.get(Configuration.ADMIN_URL)
        time.sleep(3)

        user_textbox = self.driver.find_element(By.NAME, "log")
        user_textbox.send_keys(Configuration.USER_NAME)
        pwd_textbox = self.driver.find_element(By.NAME, "pwd")
        pwd_textbox.send_keys(Configuration.PASSWORD)
        pwd_textbox.submit()
        time.sleep(3)

        dboard_loaded = self.driver.find_element(By.ID,
                                                 "wpadminbar").is_displayed()
        self.assertTrue(dboard_loaded, "Assert that dashboard is loaded")

        # LogOut
        logout_link = self.driver.find_element(By.XPATH,
                                               "//*[text()='Log Out']")
        self.driver.get(logout_link.get_attribute("href"))
        time.sleep(1)
        logout_msg = self.driver.find_element(
            By.XPATH, "//*[contains(text(),'logged out')]")
        self.assertTrue(logout_msg.is_displayed(), "Assert successful logout")
        self.driver.quit()
Example #3
0
 def test(self):
     driver = Configuration.create_chrome_driver()
     driver.get(Configuration.BLOG_URL)
     time.sleep(3)
     expected_title = "CSE Blog"
     actual_title = driver.title
     self.assertEqual(actual_title, expected_title)
Example #4
0
    def setUp(self):
        chrome_options = Options()
        chrome_options.headless = True

        self.driver = Configuration.create_chrome_driver(chrome_options)
        self.wait = WebDriverWait(self.driver, 60)
        self.driver.get(Configuration.ADMIN_URL)

        # Login
        user_textbox = self.wait.until(
            expected_conditions.element_to_be_clickable((By.NAME, "log")))
        user_textbox.send_keys(Configuration.USER_NAME)
        self.assertEqual(Configuration.USER_NAME,
                         user_textbox.get_attribute("value"),
                         "Assert the user name text")

        pwd_textbox = self.wait.until(
            expected_conditions.element_to_be_clickable((By.NAME, "pwd")))
        pwd_textbox.send_keys(Configuration.PASSWORD)
        self.assertEqual(Configuration.PASSWORD,
                         pwd_textbox.get_attribute("value"),
                         "Assert the password text")

        submit_button = self.wait.until(
            expected_conditions.element_to_be_clickable((By.ID, "wp-submit")))
        submit_button.click()

        self.wait.until(expected_conditions.presence_of_element_located,
                        "//*[text()= 'WordPress Events and News']")
    def test_(self):
        self.driver.find_element(By.LINK_TEXT, "Media").click()
        self.driver.find_element(By.LINK_TEXT, "Add New").click()

        browse_button = self.driver.find_element(By.ID, "async-upload")
        file_path = Configuration.get_upload_file_path("file-upload.jpg")

        browse_button.send_keys(file_path)

        self.driver.find_element(By.ID, "html-upload").click()
        self.wait.until(
            expected_conditions.visibility_of_element_located(
                (By.CLASS_NAME, "thumbnail")))
    def test(self):
        self.driver = Configuration.create_chrome_driver()
        self.wait = WebDriverWait(self.driver, 60)
        self.driver.get(Configuration.ADMIN_URL)

        # Login
        user_textbox = self.wait.until(
            expected_conditions.element_to_be_clickable((By.NAME, "log")))
        user_textbox.send_keys(Configuration.USER_NAME)
        self.assertEqual(Configuration.USER_NAME,
                         user_textbox.get_attribute("value"),
                         "Assert the user name text")

        pwd_textbox = self.wait.until(
            expected_conditions.element_to_be_clickable((By.NAME, "pwd")))
        pwd_textbox.send_keys(Configuration.PASSWORD)
        self.assertEqual(Configuration.PASSWORD,
                         pwd_textbox.get_attribute("value"),
                         "Assert the password text")

        submit_button = self.wait.until(
            expected_conditions.element_to_be_clickable((By.ID, "wp-submit")))
        submit_button.click()

        self.wait.until(expected_conditions.presence_of_element_located,
                        "//*[text()= 'WordPress Events and News']")

        # Logout
        logout_link = self.driver.find_element(By.XPATH,
                                               "//*[text()='Log Out']")
        self.driver.get(logout_link.get_attribute("href"))

        self.wait.until(
            expected_conditions.presence_of_element_located(
                (By.XPATH, "//*[contains(text(), 'logged out')]")))
        self.driver.quit()
 def setUpClass(self):
     CSETest.driver = Configuration.create_chrome_driver()
import time
from common.config import Configuration

driver = Configuration.create_chrome_driver()
driver.get(Configuration.BLOG_URL)
time.sleep(3)
expected_title = "dummy"
actual_title = driver.title

if expected_title != actual_title:
    raise Exception(
        "Failure: Title does not match. Expected:  <{}>  Actual: <{}>   ".
        format(expected_title, actual_title))

driver.quit()
Example #9
0
 def setUp(self):
     self.driver = Configuration.create_chrome_driver()
     self.driver.get(Configuration.ADMIN_URL)
     time.sleep(3)
 def test_(self):
     target_path = Configuration.get_screenshot_file_path("dashboard")
     self.driver.save_screenshot(target_path)
Example #11
0
 def setUp(self):
     self.driver = Configuration.create_chrome_driver()
Example #12
0
class Main(MainInterface):
    def __init__(self, config_file_path=None):
        # catch SIGINT, SIGQUIT and SIGTERM
        self.__quit_signal = threading.Event()
        signal.signal(signal.SIGINT, self.__quit)
        signal.signal(signal.SIGQUIT, self.__quit)
        signal.signal(signal.SIGTERM, self.__quit)
        # catch SIGHUP and reload configuration
        signal.signal(signal.SIGHUP, self.__reload)

        # load config
        if config_file_path is None:
            self.__config_file_path = DEFAULT_CONFIG_FILE
        else:
            self.__config_file_path = config_file_path
        self.__load_settings()

        # this is the queue that holds the frames to display
        self.__frame_queue = queue.Queue(maxsize=1)

        # animation controller
        # gets initialized in mainloop method
        self.__animation_controller = AnimationController(
            self.config, self.frame_queue)

        # the animation scheduler
        self.__animation_scheduler = self.__create_scheduler()
        self.__schedule_lock = Lock()

        # the nighttime scheduler
        self.__location = lookup(tzlocal.get_localzone_name().split("/")[1],
                                 database())
        self.__nighttime_scheduler = BackgroundScheduler()
        self.__sunrise_job = self.__nighttime_scheduler.add_job(
            func=self.apply_brightness)
        self.__sunset_job = self.__nighttime_scheduler.add_job(
            func=self.apply_brightness)
        self.__nighttime_scheduler.add_job(func=self.__calculate_nighttimes,
                                           trigger=CronTrigger(hour="0,12",
                                                               minute=0,
                                                               second=0))
        self.__calculate_nighttimes()
        self.apply_brightness()
        self.__nighttime_scheduler.start()

        # create the display object
        self.__initialize_display()

        # server interfaces
        self.__http_server = None
        self.__rest_server = None
        self.__tpm2_net_server = None

        # this signal is set by the reload method
        self.__reload_signal = EventWithUnsetSignal()

    def __load_settings(self):
        self.__config = Configuration(config_file_path=self.__config_file_path,
                                      allow_no_value=True)

        # get [MAIN] options
        self.__conf_hardware = self.__config.get(Config.MAIN.Hardware)
        self.__conf_display_width = self.__config.get(Config.MAIN.DisplayWidth)
        self.__conf_display_height = self.__config.get(
            Config.MAIN.DisplayHeight)
        self.__day_brightness = self.__config.get(Config.MAIN.DayBrightness)
        self.__night_brightness = self.__config.get(
            Config.MAIN.NightBrightness)

    def __create_scheduler(self):
        # start with an empty table
        self.__schedule_table = []

        # create the scheduler
        scheduler = BackgroundScheduler()

        # load saved jobs
        saved_jobs = self.config.get(Config.SCHEDULEDANIMATIONS.ScheduleTable)
        for job in saved_jobs:
            entry = ScheduleEntry(**job)

            # during load of the saved scheduled animations, the ANIMATION_SETTINGS attribute is a dict
            # it must be converted to the respective class instead
            animation = self.available_animations[
                entry.ANIMATION_SETTINGS["animation_name"]]
            entry.ANIMATION_SETTINGS = animation.default_animation_settings(
                **entry.ANIMATION_SETTINGS)

            # add job to the scheduler
            scheduler.add_job(func=self.start_animation,
                              trigger=CronTrigger(
                                  year=entry.CRON_STRUCTURE.YEAR,
                                  month=entry.CRON_STRUCTURE.MONTH,
                                  day=entry.CRON_STRUCTURE.DAY,
                                  week=entry.CRON_STRUCTURE.WEEK,
                                  day_of_week=entry.CRON_STRUCTURE.DAY_OF_WEEK,
                                  hour=entry.CRON_STRUCTURE.HOUR,
                                  minute=entry.CRON_STRUCTURE.MINUTE,
                                  second=entry.CRON_STRUCTURE.SECOND),
                              args=(entry.ANIMATION_SETTINGS, ),
                              kwargs={
                                  "pause_current_animation": True,
                                  "block_until_finished": True
                              },
                              id=entry.JOB_ID)

            # add it to the internal schedule table
            # no lock is needed here, because when this method is called only the main thread is running
            self.__schedule_table.append(entry)

        return scheduler

    def __initialize_display(self):
        # load display plugins
        display_loader = Loader()
        display_loader.load_plugins((BASE_DIR / "display").resolve(),
                                    plugin_base_class=AbstractDisplay)

        # create it
        try:
            self.__display = display_loader.plugins[
                self.__conf_hardware.casefold()](self.__conf_display_width,
                                                 self.__conf_display_height,
                                                 self.__display_brightness,
                                                 config=self.config)
            self.__clear_display()
        except KeyError:
            raise RuntimeError("Display hardware '{}' not known.".format(
                self.__conf_hardware))

    def __calculate_nighttimes(self):
        s = sun(self.__location.observer, date=datetime.now().date())
        if s["sunset"] < datetime.now(tz=tzlocal.get_localzone()):
            # calling after sunset, so calculate for the next day
            s = sun(self.__location.observer,
                    date=datetime.now().date() + timedelta(days=1))
        self.__sunrise = s["sunrise"]
        self.__sunset = s["sunset"]

        self.__sunrise_job.reschedule(trigger=DateTrigger(
            run_date=self.__sunrise))
        self.__sunset_job.reschedule(trigger=DateTrigger(
            run_date=self.__sunset))

    def __start_servers(self):
        # HTTP server
        if (self.__config.get(Config.MAIN.HttpServer) and
                # if the variable is set, that means we're in a reload phase
                # so the server is already started
                self.__http_server is None):
            self.__http_server = HttpServer(self)
            self.__http_server.start()

        # REST server
        if (self.__config.get(Config.MAIN.RestServer) and
                # if the variable is set, that means we're in a reload phase
                # so the server is already started
                self.__rest_server is None):
            self.__rest_server = RestServer(self)
            self.__rest_server.start()

        # TPM2Net server
        if self.__config.get(Config.MAIN.TPM2NetServer):
            self.__tpm2_net_server = Tpm2NetServer(self,
                                                   self.__conf_display_width,
                                                   self.__conf_display_height)
            threading.Thread(target=self.__tpm2_net_server.serve_forever,
                             daemon=True).start()

    def __stop_servers(self):
        # stop only the servers that are started
        # except on reload, then do not stop the HTTP and REST server
        if not self.__reload_signal.is_set():
            # HTTP server
            if self.__http_server:
                self.__http_server.stop()

            # REST server
            if self.__rest_server:
                self.__rest_server.stop()

        # TPM2Net server
        if self.__tpm2_net_server:
            self.__tpm2_net_server.shutdown()
            self.__tpm2_net_server.server_close()

    def __save_schedule_table(self):
        # this method should be surrounded by a lock
        # convert the ScheduleEntry instances to dicts (needed for file saving)
        table = []
        for entry in self.__schedule_table:
            table.append(entry.as_raw_dict())

        # save the table in the config
        self.config.set(Config.SCHEDULEDANIMATIONS.ScheduleTable, table)
        self.config.save()

    def __clear_display(self):
        self.__display.clear_buffer()
        self.__display.show()

    def __quit(self, *_):
        print("Exiting...")
        self.__quit_signal.set()

    @property
    def config(self):
        return self.__config

    @property
    def frame_queue(self):
        return self.__frame_queue

    def __reload(self, *_):
        print("Reloading...")

        # set the reload and quit signal to exit mainloop
        self.__reload_signal.set()
        self.__quit_signal.set()

    def reload(self):
        # start reload process
        self.__reload()

        # wait until the the __reload_signal is unset
        self.__reload_signal.wait_unset()

    def start_animation(self,
                        animation_settings,
                        pause_current_animation=False,
                        block_until_started=False,
                        block_until_finished=False):
        self.__animation_controller.start_animation(
            animation_settings=animation_settings,
            pause_current_animation=pause_current_animation,
            block_until_started=block_until_started,
            block_until_finished=block_until_finished)

    def schedule_animation(self, cron_structure, animation_settings):
        with self.__schedule_lock:
            job = self.__animation_scheduler.add_job(
                func=self.start_animation,
                trigger=CronTrigger(year=cron_structure.YEAR,
                                    month=cron_structure.MONTH,
                                    day=cron_structure.DAY,
                                    week=cron_structure.WEEK,
                                    day_of_week=cron_structure.DAY_OF_WEEK,
                                    hour=cron_structure.HOUR,
                                    minute=cron_structure.MINUTE,
                                    second=cron_structure.SECOND),
                args=(animation_settings, ),
                kwargs={
                    "pause_current_animation": True,
                    "block_until_finished": True
                })

            # create an entry for the schedule table
            schedule_entry = ScheduleEntry()
            schedule_entry.JOB_ID = job.id
            schedule_entry.CRON_STRUCTURE = cron_structure
            schedule_entry.ANIMATION_SETTINGS = animation_settings
            self.__schedule_table.append(schedule_entry)

            # save the new entry in the config
            self.__save_schedule_table()

    def stop_animation(self, animation_name=None, blocking=False):
        self.__animation_controller.stop_animation(animation_name,
                                                   blocking=blocking)

    def remove_scheduled_animation(self, schedule_id):
        with self.__schedule_lock:
            job_found = False
            for i in range(0, len(self.__schedule_table)):
                if self.__schedule_table[i].JOB_ID == schedule_id:
                    job_found = True
                    self.__animation_scheduler.remove_job(schedule_id)

                    # remove the entry from the table
                    del self.__schedule_table[i]
                    break

            if not job_found:
                eprint("No scheduled animation with ID '%' found!" %
                       str(schedule_id))
            else:
                # save the modified table
                self.__save_schedule_table()

    def modify_scheduled_animation(self, schedule_entry):
        with self.__schedule_lock:
            job_found = False
            for i in range(0, len(self.__schedule_table)):
                if self.__schedule_table[i].JOB_ID == schedule_entry.JOB_ID:
                    job_found = True
                    # modify the arguments
                    self.__animation_scheduler.modify_job(
                        schedule_entry.JOB_ID,
                        args=(schedule_entry.ANIMATION_SETTINGS, ))

                    # and also reschedule it
                    self.__animation_scheduler.reschedule_job(
                        schedule_entry.JOB_ID,
                        trigger=CronTrigger(
                            year=schedule_entry.CRON_STRUCTURE.YEAR,
                            month=schedule_entry.CRON_STRUCTURE.MONTH,
                            day=schedule_entry.CRON_STRUCTURE.DAY,
                            week=schedule_entry.CRON_STRUCTURE.WEEK,
                            day_of_week=schedule_entry.CRON_STRUCTURE.
                            DAY_OF_WEEK,
                            hour=schedule_entry.CRON_STRUCTURE.HOUR,
                            minute=schedule_entry.CRON_STRUCTURE.MINUTE,
                            second=schedule_entry.CRON_STRUCTURE.SECOND))

                    # replace the schedule table entry
                    self.__schedule_table[i] = schedule_entry
                    break

            if not job_found:
                eprint("No scheduled animation with ID '%' found!" %
                       str(schedule_entry.JOB_ID))
            else:
                # save the modified table
                self.__save_schedule_table()

    @property
    def available_animations(self):
        return self.__animation_controller.all_animations

    @property
    def scheduled_animations(self):
        return self.__schedule_table

    def is_animation_running(self, animation_name):
        return self.__animation_controller.is_animation_running(animation_name)

    def get_current_animation_name(self):
        return self.__animation_controller.get_current_animation_name()

    def get_day_brightness(self):
        return self.__day_brightness

    def get_night_brightness(self):
        return self.__night_brightness

    def apply_brightness(self,
                         new_day_brightness=None,
                         new_night_brightness=None):
        if new_day_brightness is not None:
            self.__day_brightness = new_day_brightness
        if new_night_brightness is not None:
            self.__night_brightness = new_night_brightness

        if (self.__night_brightness == -1 or self.__sunrise <=
                datetime.now(tz=tzlocal.get_localzone()) <= self.__sunset):
            self.__display_brightness = self.__day_brightness
        else:
            self.__display_brightness = self.__night_brightness

        self.preview_brightness(self.__display_brightness)

    def preview_brightness(self, brightness):
        # apply to the current display if it's already initialized
        if getattr(self, "_%s__display" % self.__class__.__name__,
                   None) is not None:
            self.__display.set_brightness(brightness)

    def mainloop(self):
        # start the animation controller
        self.__animation_controller.start()

        # start the animation scheduler
        self.__animation_scheduler.start()

        # start the server interfaces
        self.__start_servers()

        first_loop = True
        # run until '__quit' method was called
        while not self.__quit_signal.is_set():
            # check if there is a frame that needs to be displayed
            if not self.__frame_queue.empty():
                # get frame and display it
                self.__display.buffer = self.__frame_queue.get()
                self.__frame_queue.task_done()
                self.__display.show(gamma=True)

                # after the first frame is displayed, clear the reload signal
                if first_loop:
                    self.__reload_signal.clear()
                    first_loop = False
            else:
                # to limit CPU usage do not go faster than 60 "fps" on empty queue
                self.__quit_signal.wait(1 / 60)

        self.__animation_scheduler.shutdown()
        self.__animation_controller.stop()
        self.__clear_display()

        # stop the server interfaces
        self.__stop_servers()

        if self.__reload_signal.is_set():
            # reload settings
            self.__load_settings()

            # recreate the controller
            self.__animation_controller = AnimationController(
                self.config, self.frame_queue)

            # recreate the scheduler
            self.__animation_scheduler = self.__create_scheduler()

            # re-initialize the display
            self.__initialize_display()

            # clear quit signal
            # the reload signal gets cleared after the first frame is displayed again
            self.__quit_signal.clear()

            # restart mainloop
            self.mainloop()
Example #13
0
#!/usr/bin/env python3
import argparse
from pathlib import Path
import sys

if __name__ == '__main__':
    # cli parser
    parser = argparse.ArgumentParser(
        description="Create or Update the configuration file.")
    parser.add_argument("CONFIG_FILE_PATH",
                        type=Path,
                        help="The path of the configuration file.")

    # get config path
    args = parser.parse_args(sys.argv[1:])
    config_file_path = args.CONFIG_FILE_PATH

    if config_file_path.exists() and not config_file_path.is_file():
        raise ValueError("'%s' is not the path of a file!" %
                         str(config_file_path))
    else:
        # sys.path hack for relative import
        path = Path(__file__).parent.parent
        sys.path.append(str(path))

        from common.config import Configuration
        config = Configuration(config_file_path=config_file_path,
                               allow_no_value=True)
        config.save()