Developer Guide =============== This document provides guide to hacking and extending PieTime. Setup ----- To develop PieTime or cards, some additional setup is required. First, it's recommended to use a virtual environment, to separate from OS Python and extensions. Secondly, use ``requirements-dev.txt`` to install additional modules and tools used in development. Custom card example ------------------- .. sourcecode:: python from pie_time.card import AbstractCard import pygame class ExampleCard(AbstractCard): def initialize(self): self.sprite = pygame.surface.Surface((20, 20)) self.sprite.fill((255, 0, 0)) self.orig_sprite_rect = self.sprite.get_rect() self.orig_speed = [2, 2] self.sprite_rect = self.orig_sprite_rect self.speed = self.orig_speed def show(self): self.sprite_rect = self.orig_sprite_rect self.speed = self.orig_speed def tick(self): self.sprite_rect = self.sprite_rect.move(self.speed) if self.sprite_rect.left < 0 or self.sprite_rect.right > self.width: self.speed[0] = -self.speed[0] if self.sprite_rect.top < 0 or self.sprite_rect.bottom > self.height: self.speed[1] = -self.speed[1] self.surface.fill(self.background_color) self.surface.blit(self.sprite, self.sprite_rect) This example shows how easy it is to create custom cards for use in PieTime decks. Start by creating a custom class that inherits from *AbstractCard*. Then implement a few methods to make it display the information you need (in this example, a red square moving on the screen). Having done that, you'll be ready to use your custom card in a deck. Head on to :py:class:`pie_time.AbstractCard` documentation for more information about PieTime card API. Speed considerations -------------------- Since PieTime targets the Raspberry Pi, it's important to keep speed in mind. When developing cards, take care to do as little work as possible in the :py:meth:`pie_time.AbstractCard.tick` method. For example, WeatherCard redraws its surface only when weather conditions change. By doing so, the CPU load is reduced because the only thing PieTime has to do is blit the surface to screen. Always test the behavior of your card in low FPS. Remember, that PieTime targets small GPIO-connected LCD screens. For many of them, 20 FPS will be the best refresh rate. If your card behaves badly in such conditions, users may refrain from using it. Threading considerations ------------------------ Sometimes, it's required to perform background tasks during lifetime of the card. API exposed by Python's builtin ``threading`` module should come in handy is such situations. Take WeatherCard as an example. Once every 10 minutes, it fetches current conditions from the Internet. If you look into the card's code, there's ``_refresh_conditions`` method. It uses ``threading.Timer`` class to schedule fetching of the conditions in a separate thread of control. This way, the HTTP request (which may take some time depending on the network conditions) won't cause the PieTime application to freeze. As always with threads, you should be aware of the standard pitfalls - variable access synchronization, error handling, the GIL. Also, spawning too many threads will impact PieTime's performance. If you use threads in your card, make sure to test it on the device to see how it impacts the load. Handling events --------------- In every iteration of the main loop, PieTime reads list of current events from PyGame. This list is available for the cards to use through :py:attr:`pie_time.PieTime.events`. The application itself handles the following events: * ``QUIT`` (e.g. SIGTERM) - if this event appears, the application quits. * ``KEYDOWN`` on the key specified by :py:attr:`pie_time.PieTime.KEY_QUIT` - quits the application, * ``MOUSEBUTTONDOWN`` anywhere on the screen when it's blanked - if click to unblank is enabled, * ``MOUSEBUTTONDOWN`` in one of the regions used to manually switch bedween cards.