Skip to content

Commit 79c2d5e

Browse files
authored
Merge pull request #703 from brentru/add-pyportal-azure-learnguide
Add PyPortal Azure IoT Learning System Guide Files
2 parents 44a6892 + 2198828 commit 79c2d5e

6 files changed

Lines changed: 14077 additions & 0 deletions

File tree

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
"""
2+
GFX Helper for PyPortal Azure IoT Plant Monitor
3+
"""
4+
import board
5+
import displayio
6+
from adafruit_display_text.label import Label
7+
from adafruit_bitmap_font import bitmap_font
8+
9+
cwd = ("/"+__file__).rsplit('/', 1)[0] # the current working directory (where this file is)
10+
11+
# Fonts within /fonts folder
12+
main_font = cwd+"/fonts/EarthHeart-26.bdf"
13+
data_font = cwd+"/fonts/Collegiate-50.bdf"
14+
15+
class Azure_GFX(displayio.Group):
16+
def __init__(self, is_celsius=True):
17+
"""Creates an Azure_GFX object.
18+
:param bool is_celsius: Temperature displayed in Celsius.
19+
"""
20+
# root displayio group
21+
root_group = displayio.Group(max_size=23)
22+
board.DISPLAY.show(root_group)
23+
super().__init__(max_size=15)
24+
25+
# temperature display option
26+
self._is_celsius = is_celsius
27+
28+
# create background icon group
29+
self._icon_group = displayio.Group(max_size=3)
30+
self.append(self._icon_group)
31+
board.DISPLAY.show(self._icon_group)
32+
# create text object group
33+
self._text_group = displayio.Group(max_size=9)
34+
self.append(self._text_group)
35+
36+
self._icon_sprite = None
37+
self._icon_file = None
38+
self._cwd = cwd
39+
self.set_icon(self._cwd+"/images/azure_splash.bmp")
40+
41+
print('loading fonts...')
42+
glyphs = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.: '
43+
data_glyphs = b'012345678-,.:/FC'
44+
self.main_font = bitmap_font.load_font(main_font)
45+
self.main_font.load_glyphs(glyphs)
46+
self.data_font = bitmap_font.load_font(data_font)
47+
self.data_font.load_glyphs(data_glyphs)
48+
self.data_font.load_glyphs(('°',)) # extra glyph for temperature font
49+
50+
print('setting up labels...')
51+
self.title_text = Label(self.main_font, text="Azure Plant Monitor")
52+
self.title_text.x = 35
53+
self.title_text.y = 25
54+
self._text_group.append(self.title_text)
55+
56+
self.temp_label = Label(self.main_font, text="Temperature")
57+
self.temp_label.x = 0
58+
self.temp_label.y = 65
59+
self._text_group.append(self.temp_label)
60+
61+
self.temp_text = Label(self.data_font, max_glyphs=10)
62+
self.temp_text.x = 200
63+
self.temp_text.y = 85
64+
self._text_group.append(self.temp_text)
65+
66+
self.moisture_label = Label(self.main_font, text="Moisture Level")
67+
self.moisture_label.x = 0
68+
self.moisture_label.y = 135
69+
self._text_group.append(self.moisture_label)
70+
71+
self.moisture_text = Label(self.data_font, max_glyphs=10)
72+
self.moisture_text.x = 200
73+
self.moisture_text.y = 175
74+
self._text_group.append(self.moisture_text)
75+
76+
self.azure_status_text = Label(self.main_font, max_glyphs=15)
77+
self.azure_status_text.x = 65
78+
self.azure_status_text.y = 225
79+
self._text_group.append(self.azure_status_text)
80+
81+
board.DISPLAY.show(self._text_group)
82+
83+
84+
def display_azure_status(self, status_text):
85+
"""Displays the system status on the PyPortal
86+
:param str status_text: Description of Azure IoT status
87+
"""
88+
self.azure_status_text.text = status_text
89+
90+
def display_moisture(self, moisture_data):
91+
"""Displays the moisture from the Stemma Soil Sensor.
92+
:param int moisture_data: Moisture value
93+
"""
94+
print('Moisture Level: ', moisture_data)
95+
self.moisture_text.text = str(moisture_data)
96+
97+
def display_temp(self, temp_data):
98+
"""Displays the temperature from the Stemma Soil Sensor.
99+
:param float temp_data: Temperature value.
100+
"""
101+
if not self._is_celsius:
102+
temp_data = (temp_data * 9 / 5) + 32 - 15
103+
print('Temperature: %0.0f°F'%temp_data)
104+
if temp_data >= 212:
105+
self.temp_text.color = 0xFD2EE
106+
elif temp_data <= 32:
107+
self.temp_text.color = 0xFF0000
108+
self.temp_text.text = '%0.0f°F'%temp_data
109+
temp_data = '%0.0f'%temp_data
110+
return int(temp_data)
111+
else:
112+
print('Temperature: %0.0f°C'%temp_data)
113+
if temp_data <= 0:
114+
self.temp_text.color = 0xFD2EE
115+
elif temp_data >= 100:
116+
self.temp_text.color = 0xFF0000
117+
self.temp_text.text = '%0.0f°C'%temp_data
118+
temp_data = '%0.0f'%temp_data
119+
return int(temp_data)
120+
121+
def set_icon(self, filename):
122+
"""Sets the background image to a bitmap file.
123+
124+
:param filename: The filename of the chosen icon
125+
"""
126+
print("Set icon to ", filename)
127+
if self._icon_group:
128+
self._icon_group.pop()
129+
130+
if not filename:
131+
return # we're done, no icon desired
132+
if self._icon_file:
133+
self._icon_file.close()
134+
self._icon_file = open(filename, "rb")
135+
icon = displayio.OnDiskBitmap(self._icon_file)
136+
try:
137+
self._icon_sprite = displayio.TileGrid(icon,
138+
pixel_shader=displayio.ColorConverter())
139+
except TypeError:
140+
self._icon_sprite = displayio.TileGrid(icon,
141+
pixel_shader=displayio.ColorConverter(),
142+
position=(0,0))
143+
144+
self._icon_group.append(self._icon_sprite)
145+
board.DISPLAY.refresh_soon()
146+
board.DISPLAY.wait_for_frame()
147+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
PyPortal Azure IoT Plant Monitor
3+
====================================================
4+
Log plant vitals to Microsoft Azure IoT with
5+
your PyPortal
6+
7+
Author: Brent Rubell for Adafruit Industries, 2019
8+
"""
9+
import time
10+
import board
11+
import busio
12+
from digitalio import DigitalInOut
13+
from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager
14+
import neopixel
15+
from adafruit_azureiot import IOT_Hub
16+
from adafruit_seesaw.seesaw import Seesaw
17+
18+
# gfx helper
19+
import azure_gfx_helper
20+
21+
# Get wifi details and more from a secrets.py file
22+
try:
23+
from secrets import secrets
24+
except ImportError:
25+
print("WiFi secrets are kept in secrets.py, please add them there!")
26+
raise
27+
28+
# PyPortal ESP32 Setup
29+
esp32_cs = DigitalInOut(board.ESP_CS)
30+
esp32_ready = DigitalInOut(board.ESP_BUSY)
31+
esp32_reset = DigitalInOut(board.ESP_RESET)
32+
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
33+
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
34+
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
35+
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
36+
37+
# Soil Sensor Setup
38+
i2c_bus = busio.I2C(board.SCL, board.SDA)
39+
ss = Seesaw(i2c_bus, addr=0x36)
40+
41+
# Create an instance of the Azure IoT Hub
42+
hub = IOT_Hub(wifi, secrets['azure_iot_hub'], secrets['azure_iot_sas'], secrets['azure_device_id'])
43+
44+
# init. graphics helper
45+
gfx = azure_gfx_helper.Azure_GFX(False)
46+
47+
while True:
48+
try:
49+
# read moisture level
50+
moisture_level = ss.moisture_read()
51+
# read temperature
52+
temperature = ss.get_temp()
53+
# display soil sensor values on pyportal
54+
gfx.display_moisture(moisture_level)
55+
temperature = gfx.display_temp(temperature)
56+
print('Sending data to Azure')
57+
gfx.display_azure_status('Sending data...')
58+
hub.send_device_message(temperature)
59+
hub.send_device_message(moisture_level)
60+
gfx.display_azure_status('Data sent!')
61+
print('Data sent!')
62+
except (ValueError, RuntimeError) as e:
63+
print("Failed to get data, retrying\n", e)
64+
wifi.reset()
65+
continue
66+
time.sleep(60)

0 commit comments

Comments
 (0)