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")
view raw light.py hosted with ❤ by GitHub

Reverse Engineering
Prototyping Connected Products - Lab Experiment 1

Code and collaboration
Prototyping Connected Product - Self-Study 2

TU Delft IoT Rapid-Proto Labs Erasmus +

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.