Tuesday 27 October 2020

PyBloom coding project part 4: Organising the code

Previously in I've set out the objectives and environments for PyBloom. Now in part 4, I look at how to organise the code and pre-requisites.

Organising the code

The code should follow the technical stories described previously, but the mapping of module to story isn’t straightforward.

Mapping stories to modules

Technical Story

Code Module

Preparatory Spike

Check the current weather

Weather observation object in main script

How do I work with the Open Weather Map API?

Change the colour of the lounge bloom to display the temperature

Hue lamp object in main script

How do I work with the Philips Hue API?

Log the weather reading

Weather observation object in main script


Make the Hue colours available on an external database

Database utility

Having decided to use SQLite for my persistent data stores, how do I use it with Python and Flask?

Calculate the data points from the observation

Generate graphs function in main script


Data visualisation

Generate graphs function in main script

I don’t like MatPlotLib for data visualisation in Python. Which alternative should I use?

Serve page in local network

Web app

HTML

CSS

Having decided to use Flask to generate my website HTML from Python code, how do I use it?

Having decided to use Bootstrap to generate by CSS to format my website, how do I use it?

I want to show the same colours for the same temperature on my Bloom, on the graphs, and on the website. 

Run every hour

Running the script periodically

How do I run my program periodically, automatically?

How do I run two programs (the web server and gathering weather observations) simultaneously?


Let’s get onto the actual writing.

Prerequisites

Like all Python programs, my code builds upon libraries written by other people.

The code

Each weather reading is called an observation. The weather_observation class is responsible for fetching the current weather observation, for and for logging. Let’s get into it, starting with the third party libraries that I use.


from datetime import datetime, timedelta


Dates and times are funny to manage. Thankfully, both Python and SQLite have datetime modules that handle the complexity, simplifying the representation of the maths.


import qhue


Qhue provides a python wrapper for the Philips API, making it much more straightforward to access the lights as Python resources. 


from rgbxy import Converter

from rgbxy import GamutA


Philips Hue light colours are complicated. They use (x,y) coordinates that describe a point in a colour space.  CSS, the technology that describes the presentation of web sites, uses the RGB representation of colour. Thankfully, this library converts between the two, and even makes sure that the bulbs are able to show the colours (are within the bulb’s gamut).


import pyowm


Another wrapper, pyOWM provides a python wrapper for the OpenWeatherMap API. It provides a weather manager object that handles all the API complexity, and presents as a Python resource. The free version of the API has a limit of the number of calls allowed per month. To make sure I’m under this limit, the code writes each observation into a persistent database which can then be queried as many times as I like.


import sqlite3


To make the measurement data (and other data) persistent, it’s written into a database that can be accessed by other code objects such as the web page. Whilst there are many database technologies, I went with SQLite as it’s built into Python, so no need to download any more libraries.


import pygal


I’ve used powerful visualisation libraries like MatPlotLib and Seaborn, and they’re complicated because they’re powerful. By contrast, I found Pygal to be super easy.


from db_setup import db_connect, get_rows


I wrote my own helper utilities to make connecting to, fetching data from, then shutting the connection to my SQLite database a little easier. Whilst there are other approaches like decorator functions to do this, a utility made more sense to me. More on this when we look at the code.


Here now are the global constants:


DATETIME_STRING = '%Y-%m-%d %H:%M:%S'

FILEPATH = './app/static/'


We’re going to need these two constants later on in the code, but because they’re trivial to understand, let’s introduce them now. The first governs how the datetime function mentioned earlier works in both Python and SQLite. More on the reason for the syntax in the section on logging. 


The second constant is the file path for the web site assets. More on the reason for this file path in the section on presenting in a web page.


OWM_KEY = credentials.credentials['owm_key']

HUE_USERNAME = credentials.credentials['hue_username']

HUE_IP = credentials.credentials['hue_ip']

HOME_LOCATION = credentials.credentials['home_location']


These global constants are the secrets used by the APIs to secure the calls. You’ll need to note your own in a credentials.py file, as we’ll see in a future section.




Putting it together

from datetime import datetime, timedelta

import qhue

import pyowm

from rgbxy import Converter

from rgbxy import GamutA

import sqlite3

import pygal

from db_setup import db_connect, get_rows


DATETIME_STRING = '%Y-%m-%d %H:%M:%S'

FILEPATH = './app/static/'

OWM_KEY = credentials.credentials['owm_key']

HUE_USERNAME = credentials.credentials['hue_username']

HUE_IP = credentials.credentials['hue_ip']

HOME_LOCATION = credentials.credentials['home_location']



We're finally done with the prerequisites. In part 5 I'll start to write actual code! Also visit https://github.com/Schmoiger/pybloom for the full story.

No comments:

Post a Comment

It's always great to hear what you think. Please leave a comment, and start a conversation!