Skip to content

Commit 9aadd89

Browse files
authored
Merge pull request #2894 from adafruit/matter_display
code for Matter sensor dashboard
2 parents f8e920e + 245259c commit 9aadd89

File tree

3 files changed

+7857
-0
lines changed

3 files changed

+7857
-0
lines changed

Matter_Devices_Dashboard/code.py

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
import time
6+
import os
7+
import ssl
8+
import wifi
9+
import socketpool
10+
import microcontroller
11+
import board
12+
import digitalio
13+
import displayio
14+
from adafruit_bitmap_font import bitmap_font
15+
from adafruit_display_text import bitmap_label
16+
from adafruit_display_shapes.circle import Circle
17+
from adafruit_display_shapes.roundrect import RoundRect
18+
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
19+
import adafruit_minimqtt.adafruit_minimqtt as MQTT
20+
21+
aio_username = os.getenv("ADAFRUIT_AIO_USERNAME")
22+
aio_key = os.getenv("ADAFRUIT_AIO_KEY")
23+
24+
# feeds!
25+
temp_feed = aio_username + "/feeds/eve-temp" # temperature sensor
26+
humid_feed = aio_username + "/feeds/eve-humid" # humidity sensor
27+
lux_feed = aio_username + "/feeds/eve-light" # lux sensor
28+
occupy_feed = aio_username + "/feeds/eve-occupy" # occupation sensor
29+
light_feed = aio_username + "/feeds/nanoleaf" # lightstrip
30+
31+
# buttons
32+
button0 = digitalio.DigitalInOut(board.D0)
33+
button0.direction = digitalio.Direction.INPUT
34+
button0.pull = digitalio.Pull.UP
35+
button0_state = False
36+
button1 = digitalio.DigitalInOut(board.D1)
37+
button1.direction = digitalio.Direction.INPUT
38+
button1.pull = digitalio.Pull.DOWN
39+
button1_state = False
40+
button2 = digitalio.DigitalInOut(board.D2)
41+
button2.direction = digitalio.Direction.INPUT
42+
button2.pull = digitalio.Pull.DOWN
43+
button2_state = False
44+
45+
display = board.DISPLAY
46+
group = displayio.Group()
47+
display.root_group = group
48+
49+
# load background bitmap
50+
bitmap = displayio.OnDiskBitmap("/tft_bg.bmp")
51+
tile_grid = displayio.TileGrid(bitmap, pixel_shader=bitmap.pixel_shader)
52+
group = displayio.Group()
53+
group.append(tile_grid)
54+
55+
# bitmap font
56+
font_file = "/roundedHeavy-26.bdf"
57+
font = bitmap_font.load_font(font_file)
58+
# text elements
59+
temp_text = bitmap_label.Label(font, text="00.0°C", x=55, y=70, color=0xFFFFFF)
60+
group.append(temp_text)
61+
humid_text = bitmap_label.Label(font, text="00.0%", x=120, y=70, color=0xFFFFFF)
62+
group.append(humid_text)
63+
lux_text = bitmap_label.Label(font, text="00 lx", x=190, y=70, color=0xFFFFFF)
64+
group.append(lux_text)
65+
occupy_text = bitmap_label.Label(font, text="Occupied?", x=128,
66+
y=display.height - 12, color=0xFFFFFF)
67+
group.append(occupy_text)
68+
onOff_circ = Circle(display.width - 12, display.height - 12, 10, fill=0xcc0000)
69+
group.append(onOff_circ)
70+
scene_select = RoundRect(0, 0, 42, 40, 8, fill=None, outline=0xcccc00, stroke=6)
71+
scene_y = [0, int(display.height / 2) - int(scene_select.height / 2),
72+
display.height - scene_select.height - 1]
73+
group.append(scene_select)
74+
75+
display.root_group = group
76+
print()
77+
print("Connecting to WiFi...")
78+
# connect to your SSID
79+
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))
80+
print("Connected to WiFi!")
81+
82+
# pylint: disable=unused-argument
83+
# Define callback methods which are called when events occur
84+
def connected(client, userdata, flags, rc): # pylint: disable=unused-argument
85+
# This function will be called when the client is connected
86+
# successfully to the broker.
87+
print("Connected to Adafruit IO!")
88+
# Subscribe to all changes on feeds
89+
client.subscribe(temp_feed)
90+
client.subscribe(humid_feed)
91+
client.subscribe(lux_feed)
92+
client.subscribe(occupy_feed)
93+
client.subscribe(light_feed)
94+
95+
def disconnected(client, userdata, rc): # pylint: disable=unused-argument
96+
# This method is called when the client is disconnected
97+
print("Disconnected from Adafruit IO!")
98+
99+
def on_message(client, topic, msg): # pylint: disable=unused-argument
100+
# This method is called when a topic the client is subscribed to
101+
# has a new message.
102+
print(f"New message on topic {topic}")
103+
104+
def on_temp_msg(client, topic, msg):
105+
print(f"temp feed data: {msg}°C")
106+
temp_text.text = f"{float(msg):.01f}°C"
107+
108+
def on_humid_msg(client, topic, msg):
109+
print(f"humid feed data: {msg}%")
110+
humid_text.text = f"{float(msg):.01f}%"
111+
112+
def on_lux_msg(client, topic, msg):
113+
print(f"lux feed data: {msg} lx")
114+
lux_text.text = f"{float(msg):.00f} lx"
115+
116+
def on_occupy_msg(client, topic, msg):
117+
print(f"occupation feed data: {msg}")
118+
if msg == "1":
119+
onOff_circ.fill = 0x00cc00
120+
else:
121+
onOff_circ.fill = 0xcc0000
122+
123+
def on_light_msg(client, topic, msg):
124+
print(f"light scene selected: {msg}")
125+
scene_select.y = scene_y[int(msg)]
126+
127+
pool = socketpool.SocketPool(wifi.radio)
128+
ssl_context = ssl.create_default_context()
129+
# Initialize an Adafruit IO HTTP API object
130+
mqtt_client = MQTT.MQTT(
131+
broker="io.adafruit.com",
132+
port=1883,
133+
username=aio_username,
134+
password=aio_key,
135+
socket_pool=pool,
136+
ssl_context=ssl_context,
137+
)
138+
# Setup the callback methods above
139+
mqtt_client.on_connect = connected
140+
mqtt_client.on_disconnect = disconnected
141+
mqtt_client.on_message = on_message
142+
mqtt_client.add_topic_callback(temp_feed, on_temp_msg)
143+
mqtt_client.add_topic_callback(humid_feed, on_humid_msg)
144+
mqtt_client.add_topic_callback(lux_feed, on_lux_msg)
145+
mqtt_client.add_topic_callback(occupy_feed, on_occupy_msg)
146+
mqtt_client.add_topic_callback(light_feed, on_light_msg)
147+
148+
# Connect the client to the MQTT broker.
149+
print("Connecting to Adafruit IO...")
150+
mqtt_client.connect()
151+
152+
clock_clock = ticks_ms()
153+
clock_timer = 5 * 1000
154+
155+
while True:
156+
try:
157+
if ticks_diff(ticks_ms(), clock_clock) >= clock_timer:
158+
mqtt_client.loop(timeout=1)
159+
clock_clock = ticks_add(clock_clock, clock_timer)
160+
# reset button state on release
161+
if button0.value and button0_state:
162+
button0_state = False
163+
if not button1.value and button1_state:
164+
button1_state = False
165+
if not button2.value and button2_state:
166+
button2_state = False
167+
# buttons change light scenes
168+
if not button0.value and not button0_state:
169+
mqtt_client.publish(light_feed, 0)
170+
scene_select.y = scene_y[0]
171+
button0_state = True
172+
if button1.value and not button1_state:
173+
mqtt_client.publish(light_feed, 1)
174+
scene_select.y = scene_y[1]
175+
button1_state = True
176+
if button2.value and not button2_state:
177+
mqtt_client.publish(light_feed, 2)
178+
scene_select.y = scene_y[2]
179+
button2_state = True
180+
except Exception as error: # pylint: disable=broad-except
181+
print(error)
182+
mqtt_client.disconnect()
183+
time.sleep(5)
184+
microcontroller.reset()

0 commit comments

Comments
 (0)