In this second module, you will get started with the fundamentals of programming in Python yourself. In particular, you will look at how to achieve certain light bulb behaviour, given the working system that you now have.
After this module, you should be able to:
Explain the role of Python in prototyping, the concept of version control systems and code library.
Use the fundamentals of programming, including states and control flow, to control the behaviour of a connected light bulb.
Test your code with test Units
Specify the behaviour of a connected product with state machine and flow chart.
Collaborate with your team members around code development with Git and GitHub.
Self-Study Material
In this module, the self-study material focus on the fundamentals of programming. While this course is not a programming course, we will explore the necessary basics to get started such as state and code management. We will motivate the choice of Python for this course, and introduce a few specifics to Python. Finally, we will introduce the concept of Version Control Systems and code library, necessary step to use code from others and collaborate.
Assignment
In this assignment, you will experience the basics of Python programming. You will write a program that control the connected light bulb. You will rely on code written by others developers and share it with the rest of your team.
Programming Environment: VS Code
Code Management: Git, GitHub
Lab Xp
Through the second assignment, we shaped the behaviour of our connected lightbulb with Python. In this lab experiment, we will start collecting data from the light bulb.
Technique: Live-Data Prototype
Live Session
In this session, we play with the basic programming concept in Python. We will walk you through the workflow of collaborating with Git and GitHub. As usual, we will keep a significant room for your questions.
Coaching Session
This will be the first group session with your coach. You will receive feedback about what you reported on your GitHub repository.
Snippet of code for this module
import asyncio | |
from kasa import SmartBulb | |
from time import sleep, time | |
from dcd.bucket.thing import Thing | |
class Lightbulb: | |
""" | |
This class takes care of shaping the behaviour of the lightbulb. | |
This is the result of Module 2 (https://id5415.datacentricdesign.org/module2) | |
""" | |
def __init__(self, ip_address, thing_id, private_key_path): | |
self.ip_address = ip_address | |
# Create an attribute thing_bulb of type Thing, with the thing_id and private_key_path | |
self.thing_bulb = Thing(thing_id=thing_id, private_key_path=private_key_path) | |
# Create an attribute prop_status, result of find_or_create_property() | |
self.prop_status = self.thing_bulb.find_or_create_property("Lightbulb Status", "LIGHTBULB_STATUS") | |
async def connect(self): | |
""" | |
Establish the connection with the lightbulb. | |
""" | |
# Create an attribute bulb of type SmartBulb | |
self.bulb = SmartBulb(self.ip_address) | |
# Establish the the connection with the lightbulb with update() | |
await self.bulb.update() | |
async def blink(self, num_iterations=10, blink_duration=1): | |
""" | |
This method makes the lightbulb blink x times (num_iterations), each spaced by a number of seconds (blink_duration) | |
Args: | |
num_iterations (int, optional): Number of iterations to repeat. Defaults to 10. | |
blink_duration (int, optional): Duration of each ON and OFF period. Defaults to 1. | |
""" | |
# For num_iteration | |
for x in range(num_iterations): | |
# Use self.bulb to turn on the light | |
result = await self.bulb.turn_on() | |
# Transform the result into a list | |
values = bulb_result_to_list(result) | |
# Use self.prop_status to send the new value to Bucket | |
self.prop_status.update_values(values) | |
# sleep | |
sleep(blink_duration) | |
# Use self.bulb to turn off the light | |
result = await self.bulb.turn_off() | |
# Transform the result into a list | |
values = bulb_result_to_list(result) | |
# Use self.prop_status to send the new value to Bucket | |
self.prop_status.update_values(values) | |
# sleep | |
sleep(blink_duration) | |
def pulse(self): | |
""" | |
This method makes the lightbulb pulse. | |
To be defined. | |
""" | |
def morse(self): | |
""" | |
This method makes the lightbulb flash morse code. | |
To be defined. | |
""" | |
def bulb_result_to_list(bulb_result): | |
""" | |
This function transform a kasa lightbulb result into a list of values. | |
When the light is off, data is extracted from the subkey 'dft_on_state'. | |
Args: | |
bulb_result (dict): Dictionary of values returned by the a kasa command | |
Returns: | |
(list) : A list containing all fields of the data record. | |
""" | |
on_off = bulb_result.get("on_off") | |
mode = bulb_result.get("mode") | |
hue = bulb_result.get("hue") | |
saturation = bulb_result.get("saturation") | |
color_temp = bulb_result.get("color_temp") | |
brightness = bulb_result.get("brightness") | |
# The light is off, the info can be found in 'dft_state' | |
if (on_off == 0): | |
dft_state = bulb_result.get("dft_on_state") | |
mode = dft_state.get("mode") | |
hue = dft_state.get("hue") | |
saturation = dft_state.get("saturation") | |
color_temp = dft_state.get("color_temp") | |
brightness = dft_state.get("brightness") | |
# We return a list with all values | |
return [on_off, mode, hue, saturation, color_temp, brightness] | |
def store_csv_data(values): | |
""" | |
This function takes a list of values, convert it into a CSV string | |
and appends it to the file 'data/light.csv' | |
The current timestamp is added in front (as the first column) in milliseconds. | |
Args: | |
values (list): List of values to write into the file | |
""" | |
# Get timestamp in millisecondes | |
timestamp = str(int(time()) * 1000) | |
values_with_time = [ timestamp ] + values | |
# Convert all values into strings and join them together with a comma ',' | |
csv_line = ",".join(str(x) for x in values_with_time) | |
# Open the file and append the new line at the end | |
with open("data/light.csv", "a") as datafile: | |
datafile.write(csv_line + "\n") |
The European Commission's support for the production of this publication does not constitute an endorsement of the contents, which reflect the views only of the authors, and the Commission cannot be held responsible for any use which may be made of the information contained therein.