Skip to content

Commit 70f1c89

Browse files
author
Jim Bennett
committed
Refactoring the structure
1 parent eb3a751 commit 70f1c89

14 files changed

+672
-314
lines changed

README.md

+6-311
Large diffs are not rendered by default.

app/app-blinkt.py

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import blinkt
2+
import os, asyncio
3+
from dotenv import load_dotenv
4+
from azure.iot.device.aio import IoTHubDeviceClient, ProvisioningDeviceClient
5+
from azure.iot.device import MethodResponse
6+
7+
load_dotenv()
8+
9+
id_scope = os.getenv('ID_SCOPE')
10+
device_id = os.getenv('DEVICE_ID')
11+
primary_key = os.getenv('PRIMARY_KEY')
12+
13+
blinkt.set_brightness(1)
14+
15+
def set_colour(colour):
16+
r = '0x' + colour[0:2]
17+
g = '0x' + colour[2:4]
18+
b = '0x' + colour[4:6]
19+
20+
r_value = int(r, 0)
21+
g_value = int(g, 0)
22+
b_value = int(b, 0)
23+
24+
print('Updating color: r =', r_value, ', g =', g_value, ', b =', b_value)
25+
26+
blinkt.set_all(r_value, g_value, b_value)
27+
blinkt.show()
28+
29+
async def main():
30+
# provision the device
31+
async def register_device():
32+
provisioning_device_client = ProvisioningDeviceClient.create_from_symmetric_key(
33+
provisioning_host='global.azure-devices-provisioning.net',
34+
registration_id=device_id,
35+
id_scope=id_scope,
36+
symmetric_key=primary_key,
37+
)
38+
39+
return await provisioning_device_client.register()
40+
41+
results = await asyncio.gather(register_device())
42+
registration_result = results[0]
43+
44+
# build the connection string
45+
conn_str='HostName=' + registration_result.registration_state.assigned_hub + \
46+
';DeviceId=' + device_id + \
47+
';SharedAccessKey=' + primary_key
48+
49+
# The client object is used to interact with your Azure IoT Central.
50+
device_client = IoTHubDeviceClient.create_from_connection_string(conn_str)
51+
52+
# connect the client.
53+
print('Connecting')
54+
await device_client.connect()
55+
print('Connected')
56+
57+
# Get the current colour
58+
twin = await device_client.get_twin()
59+
print('Got twin: ', twin)
60+
61+
try:
62+
desired_colour = twin['reported']['colour']
63+
set_colour(desired_colour)
64+
except Exception as ex:
65+
print("Couldn't load twin,")
66+
67+
# listen for commands
68+
async def command_listener(device_client):
69+
while True:
70+
method_request = await device_client.receive_method_request()
71+
72+
print('Call made to', method_request.name)
73+
74+
colour = method_request.payload
75+
76+
print('payload', colour)
77+
78+
if isinstance(colour, dict):
79+
colour = colour['colour']
80+
81+
print('payload', colour)
82+
83+
set_colour(colour)
84+
85+
payload = {'result': True, 'data': colour}
86+
method_response = MethodResponse.create_from_method_request(
87+
method_request, 200, payload
88+
)
89+
await device_client.send_method_response(method_response)
90+
91+
# Write the colour back as a property
92+
await device_client.patch_twin_reported_properties({'colour':colour})
93+
94+
# async loop that controls the lights
95+
async def main_loop():
96+
global mode
97+
while True:
98+
await asyncio.sleep(1)
99+
100+
listeners = asyncio.gather(command_listener(device_client))
101+
102+
await main_loop()
103+
104+
# Cancel listening
105+
listeners.cancel()
106+
107+
# Finally, disconnect
108+
await device_client.disconnect()
109+
110+
if __name__ == '__main__':
111+
asyncio.run(main())

app/app.py app/app-unicornhat.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import unicornhat as uh
2-
import os, asyncio, threading, random, time
2+
import os, asyncio
33
from dotenv import load_dotenv
44
from azure.iot.device.aio import IoTHubDeviceClient, ProvisioningDeviceClient
55
from azure.iot.device import MethodResponse

app/install-blinkt.sh

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/bash
2+
3+
# Update all the things
4+
sudo apt-get update
5+
sudo apt-get -y upgrade
6+
7+
# Install the blinkt stuff
8+
promptreboot="no"
9+
curl https://get.pimoroni.com/blinkt | bash -s -- -y
10+
11+
# Create a folder for the app
12+
mkdir ~/BusyLight
13+
14+
# Get the IoT Central settings
15+
echo What is the IoT Central ID Scope?
16+
read id_scope
17+
18+
echo What is the device ID?
19+
read device_id
20+
21+
echo What is the primary key?
22+
read primary_key
23+
24+
# Create the .emv file
25+
echo "ID_SCOPE=$id_scope" >> ~/BusyLight/.env
26+
echo "DEVICE_ID=$device_id" >> ~/BusyLight/.env
27+
echo "PRIMARY_KEY=$primary_key" >> ~/BusyLight/.env
28+
29+
# DOwnload the app files
30+
echo Downloading files...
31+
32+
curl -L -o ~/BusyLight/requirements.txt https://github.com/jimbobbennett/BusyLight/releases/download/v0.2/requirements-blinkt.txt
33+
curl -L -o ~/BusyLight/app.py https://github.com/jimbobbennett/BusyLight/releases/download/v0.2/app-blinkt.py
34+
35+
# Install the Python requirements
36+
echo Installing requirements...
37+
38+
sudo pip3 install -r ~/BusyLight/requirements.txt
39+
40+
# Add the control to the crontab
41+
42+
sudo crontab -l > cron.tmp
43+
echo @reboot /usr/bin/python3 /home/pi/BusyLight/app.py >> cron.tmp
44+
sudo crontab cron.tmp
45+
rm cron.tmp
46+
47+
# Done, so reboot
48+
49+
echo Rebooting...
50+
51+
sudo reboot

app/install.sh app/install-unicornhat.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ echo "PRIMARY_KEY=$primary_key" >> ~/BusyLight/.env
2929
# DOwnload the app files
3030
echo Downloading files...
3131

32-
curl -L -o ~/BusyLight/requirements.txt https://github.com/jimbobbennett/BusyLight/releases/download/v0.1/requirements.txt
33-
curl -L -o ~/BusyLight/app.py https://github.com/jimbobbennett/BusyLight/releases/download/v0.1/app.py
32+
curl -L -o ~/BusyLight/requirements.txt https://github.com/jimbobbennett/BusyLight/releases/download/v0.2/requirements-unicornhat.txt
33+
curl -L -o ~/BusyLight/app.py https://github.com/jimbobbennett/BusyLight/releases/download/v0.2/app-unicornhat.py
3434

3535
# Install the Python requirements
3636
echo Installing requirements...

app/requirements-blinkt.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
blinkt
2+
azure-iot-device
3+
python-dotenv
File renamed without changes.

images/HttpTrigger.png

51.4 KB
Loading

steps/calendar_control.md

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Control the lights from an Office 365 calendar
2+
3+
The lights can be controlled from your Office365 calendar using an Azure Logic App. You can set the lights to red (`FF0000`) when a meeting starts, then back to green (`00FF00`) when your meeting ends.
4+
5+
## Create the logic app
6+
7+
1. Open the Azure Portal at [portal.azure.com](https://portal.azure.com/?WT.mc_id=busylight-github-jabenn)
8+
9+
1. Log in if you need to using your Microsoft account. If you don't have an Azure account follow the [instructions above](https://github.com/jimbobbennett/BusyLight/tree/master#set-up-the-iot-central-app) to create one.
10+
11+
1. Select **+ Create a resource**
12+
13+
1. Search for `Logic App`, select it then select **Create**
14+
15+
1. Select your Azure subscription
16+
17+
1. For the *Resource group* select **Create new** and name the new resource group **BusyLight**
18+
19+
> Resource groups are logical groupings of Azure services, allowing you to manage all the services for a particular application or project together.
20+
21+
1. Name the logic app `CalendarControl`
22+
23+
1. Select the *location* closest to you
24+
25+
1. Select **Review + create**, then **Create**
26+
27+
The logic app will be created, and when it is ready select **Go to resource**
28+
29+
## Create a trigger
30+
31+
1. When you first open the Logic App it will take you to the designer. From the *Templates* section, select **Blank logic app**
32+
33+
1. Search the connectors and triggers for `office 365 outlook` and select the **Office 365 Outlook** connector
34+
35+
1. Select the **When an upcoming event is starting soon** trigger
36+
37+
1. The designer will show the new trigger. Select **Sign In** and sign in with your Office 365 account.
38+
39+
1. Select your calendar in the *Calendar Id* drop down
40+
41+
> If you have multiple calendars to check, you will need to create multiple Logic Apps.
42+
43+
1. Leave the look ahead time at 15 minutes
44+
45+
1. Set an appropriate interval to poll for new items. Depending on how far in advance meetings can added to your calendar you can choose a suitable interval, as you pay for each poll. I use 10 minutes as I don't get meetings appearing in my calendar with less notice than that.
46+
47+
> This value needs to be less than the look ahead time otherwise events might be missed
48+
49+
### Wait till the event starts
50+
51+
The trigger is fired when it sees an upcoming event, so the app needs to delay till the event actually starts before changing the light to red. Logic app triggers and actions can pass data between them, so the Office 365 connector can pass the start and end times to the next action in the app.
52+
53+
There is a small snag however - date and time formats are hard! The date format passed from the Office connector is not quite right for the one expected by the delay actions, so needs to be adjusted.
54+
55+
1. Select **+ New step**
56+
57+
1. Search for `Schedule` and select **Schedule**
58+
59+
1. Select the **Delay until** action
60+
61+
1. Select the *Timestamp* value and a box should pop up allowing you to build an expression
62+
63+
1. Select the **Expression** tab, then select **Concat**
64+
65+
![Adding concat to the expression](../images/BuildExpression1.png)
66+
67+
1. Select the **Dynamic content** tab and select **Start time**. If you can't see this, select **See more** from the top of the list.
68+
69+
1. Select the expression, and add `, 'Z'` before the last bracket. The select **OK**.
70+
71+
![Adding Z to the expression](../images/BuildExpression2.png)
72+
73+
### Execute the IoT Central command to change the light color
74+
75+
The delay will hold till the meeting is about to start, so the next step is to connect to IoT Central to execute the command. To do this, you will need the IoT Central application Id and device Id.
76+
77+
1. Open your IoT Central app
78+
79+
1. Select **Administration** from the left-hand menu
80+
81+
1. Select **Your application** from the *Administration* menu
82+
83+
1. Take a note of the *Application ID*
84+
85+
1. Select **Devices** from the left-hand menu
86+
87+
1. Take a note of the *Device Id* of your device
88+
89+
Once you have this Id, you can create the connector
90+
91+
1. Head back to your logic app
92+
93+
1. Select **+ New step**
94+
95+
1. Search for `Azure IoT Central`, then select **Azure IoT Central**
96+
97+
1. Select the **Run a command** action
98+
99+
1. Once the action appears, select **Sign in** and log in with your Azure account if required
100+
101+
1. Drop down the *Application* box and select **Enter custom value**
102+
103+
1. Enter in the Application ID you noted down earlier
104+
105+
1. Drop down the *Device Template* and select `Busy Light (1.0.0)`
106+
107+
1. Enter your device id in the *Device* box
108+
109+
1. Drop down the *Command* and select `Update Colour`
110+
111+
1. Drop down *Add a new parameter* and check the box next to **Colour**
112+
113+
1. Set the value of *Colour* to be the colour you want when you are in a meeting, using a 6 character RGB hex string. For example, for red enter `FF0000`
114+
115+
## Handle the event ending
116+
117+
Repeat the two steps above to add another Delay Until and Run a Command action to the app. The second delay should use the *End time* instead of the *Start time*, and for the colour use the colour you want when you are not in a meeting, such as `00FF00` for green.
118+
119+
## Save the logic app
120+
121+
1. Select **Save** from the Logic App designer menu to save the Logic App and enable it.
122+
123+
## Test the logic app
124+
125+
Add an upcoming event to your calendar - far enough away that the poll will be run once. Your light will turn red when the event starts and green when it finishes.
126+
127+
<hr>
128+
129+
In this step you created an Azure Logic app to control the lights from your Office356 calendar. [Check out the other trigger options](./connect-logic-app.md).

steps/configure-iot-central.md

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Configure IoT Central
2+
3+
In the [previous step](./set-up-hardware.md), you put together the hardware based around a Raspberry Pi. In this step, you will set up Azure IoT Central to control the device.
4+
5+
## What is Azure IoT Central
6+
7+
My favorite IoT cloud service is [Azure IoT Central](https://azure.microsoft.com/services/iot-central/?WT.mc_id=busylight-github-jabenn). This is a software as a service (SaaS) platform that allows devices to send data to and be controlled from the cloud. I can use this to send commands to the device to change the color of the light. I can also use to cache the current color so that if the device resets, it can retain it's previous color setting.
8+
9+
## Set up the IoT Central app
10+
11+
1. Head to [aka.ms/BusyLightTemplate](https://aka.ms/BusyLightTemplate). This link is to a pre-configured application template that you can use to create the IoT Central application
12+
13+
1. You may be prompted to sign in, so sign in with your Microsoft account. If you don't have one you can create one during this step. A Microsoft account can be created with an email address from any provider, it doesn't just have to be hotmail or outlook.
14+
15+
1. Give the application a name and a URL. The URL will need to be globally unique across all IoT central apps so add something personal or leave the auto-generated name.
16+
17+
1. Select a pricing plan. You can have a free plan for 7 days without an Azure account, or a standard plan using an Azure account. Every account has 2 devices for free, so as long as you are only using 1 or 2 devices then you will never have to pay.
18+
19+
You will need an Azure subscription for a later step, and you can sign up for free:
20+
21+
* If you are a student aged 18 and up and have an email address from an academic institution, you can sign up for the free Azure for Students offer at [azure.microsoft.com/free/students](https://azure.microsoft.com/free/students/?WT.mc_id=busylight-github-jabenn) without a credit card. At the time of writing this gives you $100 of credit to use over 12 months, as well as free tiers of a number of services for that 2 months. At the end of the 12 months, if you are still a student you can renew and get another $100 in credit and 12 months of free services.
22+
23+
* If you are not a student, you can sign up at [azure.microsoft.com/free](https://azure.microsoft.com/free/?WT.mc_id=busylight-github-jabenn). You will need a credit card for verification purposes only, you will not be billed unless you decide to upgrade your account to a paid offering. At the time of writing the free account will give you US$200 of free credit to spend on what you like in the first 30 days, 12 months of free services, plus a load of services that have tiers that are always free.
24+
25+
If you go with a standard plan, select your *Directory*, *Azure subscription* and the *Location* nearest to you.
26+
27+
If you go with the free plan, enter your contact information.
28+
29+
1. Select **Create**
30+
31+
The IoT Central app will be provisioned and the dashboard will be loaded.
32+
33+
## Create a device
34+
35+
The app that is created contains everything you need to get going - except a configured device. From this app you can configure one or more devices and control these.
36+
37+
1. Select **Devices** from the left-hand menu
38+
39+
1. Select *Busy Light* from the **Devices** list
40+
41+
1. Select **+ New** from the top menu
42+
43+
1. Give the device a name and an Id, then select **Create**
44+
45+
1. Select the newly created device, then select **Connect** from the top menu. This will show some connection values.
46+
47+
1. Take a note of the *ID scope*, *Device ID* and *Primary key*
48+
49+
![The connection dialog](../images/ConnectionDialog.png)
50+
51+
Repeat this for as many devices as you want to control.
52+
53+
<hr>
54+
55+
In this step you set up Azure IoT Central to control the device. In the [next step](./install-pi-software.md) you will install the software on the Pi.

0 commit comments

Comments
 (0)