To configure Docker within the development environment of the screenly/playground, follow the steps detailed below. This section involves creating a Docker container that encapsulates the necessary dependencies and configurations for running the application locally for development purposes.

Dockerfile Explanation

The Dockerfile is key to setting up the development environment. It defines how the Docker image is built and what dependencies are needed to run the application.

Example: Dockerfile

FROM python:3-alpine

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY app.py .

CMD python app.py

Breakdown of Instructions:

  1. Base Image Selection:

    • FROM python:3-alpine: Uses the lightweight Alpine variant of Python 3 as the base image, providing a minimal footprint for the development environment.
  2. Setting the Working Directory:

    • WORKDIR /usr/src/app: Sets the working directory inside the container. All subsequent commands will be run from this directory.
  3. Adding Dependencies:

    • COPY requirements.txt ./: Copies the requirements.txt file into the image.
    • RUN pip install --no-cache-dir -r requirements.txt: Installs Python dependencies listed in requirements.txt. The --no-cache-dir option ensures no cache is saved, making the image smaller.
  4. Copying Application Code:

    • COPY app.py .: Copies the main application file app.py into the working directory within the container.
  5. Command to Run the Application:

    • CMD python app.py: Specifies the command to run when the container starts, in this case, executing app.py with Python.

Application Logic

The app.py file contains the core logic of the application that interacts with the Screenly API and checks the weather conditions to determine if the playlist should be enabled or disabled.

Example: app.py

import logging
import os
import requests
import sys
from time import sleep

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
ch = logging.StreamHandler()
logger.addHandler(ch)

# Screenly config
PLAYLIST_ID = os.getenv('PLAYLIST_ID')
SCREENLY_TOKEN = os.getenv('TOKEN')
HOST = 'https://api.screenlyapp.com'

# Weather service API key and target location
OPENWEATHERMAP_API_KEY = os.getenv('OPENWEATHERMAP_API_KEY')
LAT = os.getenv('LAT')
LNG = os.getenv('LNG')

# LOGIC
TEMP_THRESHOLD = os.getenv('TEMP_THRESHOLD')
ABOVE_OR_BELOW = os.getenv('ABOVE_OR_BELOW')
RETRY_TIMEOUT = float(os.getenv('RETRY_TIMEOUT', default=5 * 60))

def get_temperature():
    payload = {
            'lat': LAT,
            'lon': LNG,
            'units': 'metric',
            'appid': OPENWEATHERMAP_API_KEY
    }
    weather_lookup = requests.get(
        'https://api.openweathermap.org/data/2.5/weather',
        params=payload
    )

    if not weather_lookup.ok:
        logger.error('Failed to perform weather lookup.')
        return

    return weather_lookup.json()['main']['temp']

def control_playlist(requestor, enable=True):
    requestor.patch(
        '{}/api/v3/playlists/{}/'.format(HOST, PLAYLIST_ID),
        {"is_enabled": enable}
    )

def main():
    if not (OPENWEATHERMAP_API_KEY and LAT and LNG):
        logger.error('Missing weather variables.')
        sys.exit(1)

    if not (TEMP_THRESHOLD and ABOVE_OR_BELOW):
        logger.error('Missing logic variables.')
        sys.exit(1)

    session = requests.Session()
    session.headers["Authorization"] = "Token {}".format(SCREENLY_TOKEN)

    below = 'below' in ABOVE_OR_BELOW.lower()
    above = 'above' in ABOVE_OR_BELOW.lower()

    enabled = None

    if below and above:
        logger.error('Specify above or below. Not both.')
        sys.exit(1)

    switch_criteria = (
        lambda temperature: temperature < float(TEMP_THRESHOLD)
    )

    while True:
        temperature = get_temperature()
        logger.info('Got temperature reading: {}'.format(temperature))

        if switch_criteria(temperature):
            if enabled in [False, None]:
                control_playlist(session, enable=True)
                enabled = True
                logger.info('Enabling playlist')
            else:
                logger.info('Playlist is already enabled')
        else:
            if enabled in [None, True]:
                control_playlist(session, enable=False)
                enabled = False
                logger.info('Disabling playlist')
            else:
                logger.info('Playlist is already disabled')

        logger.info('Sleeping for {} seconds'.format(RETRY_TIMEOUT))
        sleep(RETRY_TIMEOUT)

if __name__ == '__main__':
    main()

Key Points of Application Logic:

  • The application retrieves the current temperature based on latitude and longitude using the OpenWeatherMap API.
  • Depending on the temperature and thresholds specified, it enables or disables a playlist in the Screenly environment.
  • It continuously checks the temperature at a defined timeout interval (RETRY_TIMEOUT) and takes appropriate actions based on the criteria set (whether the temperature is above or below a threshold).

By using this Docker setup in the development environment, developers can test changes to the application efficiently and ensure everything works in a contained and reproducible environment.

Source: Code segments provided above.