Skip to content

Commit 15d9d0f

Browse files
authored
Merge pull request #2260 from kattni/wifi-mailbox-notifier
Add WiFi mailbox notifier code.
2 parents 180e514 + e7a2893 commit 15d9d0f

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

WiFi_Mailbox_Notifier/code.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# SPDX-FileCopyrightText: 2022 Kattni Rembor for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""CircuitPython WiFi Mailbox Notifier"""
6+
7+
import time
8+
import ssl
9+
import alarm
10+
import board
11+
import digitalio
12+
import analogio
13+
import wifi
14+
import socketpool
15+
import microcontroller
16+
import adafruit_requests
17+
from adafruit_io.adafruit_io import IO_HTTP
18+
19+
# Get WiFi/Adafruit IO details from secrets.py
20+
try:
21+
from secrets import secrets
22+
except ImportError:
23+
print("Please create secrets.py and add your WiFi and AIO credentials there!")
24+
raise
25+
26+
# Update to True if you want metadata sent to Adafruit IO. Defaults to False.
27+
METADATA = False
28+
29+
# Initialise metadata.
30+
if alarm.wake_alarm:
31+
print("Awake", alarm.wake_alarm)
32+
# Increment wake count by 1.
33+
alarm.sleep_memory[0] += 1
34+
else:
35+
print("No wake up alarm")
36+
# Set wake count to 0.
37+
alarm.sleep_memory[0] = 0
38+
# Set error count to 0.
39+
alarm.sleep_memory[2] = 0
40+
41+
# Set up battery monitoring.
42+
voltage_pin = analogio.AnalogIn(board.VOLTAGE_MONITOR)
43+
# Take the raw voltage pin value, and convert it to voltage.
44+
voltage = ((voltage_pin.value * 2) * 3.3) / 65536
45+
46+
# Set up red LED.
47+
led = digitalio.DigitalInOut(board.LED)
48+
led.switch_to_output()
49+
50+
# Set up the alarm pin.
51+
switch_pin = digitalio.DigitalInOut(board.D27)
52+
switch_pin.pull = digitalio.Pull.UP
53+
54+
55+
# Send the data. Requires a feed name and a value to send.
56+
def send_io_data(feed, value):
57+
"""
58+
Send data to Adafruit IO.
59+
60+
Provide an Adafruit IO feed name, and the value you wish to send.
61+
"""
62+
return io.send_data(feed["key"], value)
63+
64+
65+
# Print wake count to serial console.
66+
print("Wake count:", alarm.sleep_memory[0])
67+
68+
# Connect to WiFi
69+
try:
70+
wifi.radio.connect(secrets["ssid"], secrets["password"])
71+
print("Connected to {}!".format(secrets["ssid"]))
72+
print("IP:", wifi.radio.ipv4_address)
73+
74+
pool = socketpool.SocketPool(wifi.radio)
75+
requests = adafruit_requests.Session(pool, ssl.create_default_context())
76+
# WiFi connectivity fails with error messages, not specific errors, so this except is broad.
77+
except Exception as e: # pylint: disable=broad-except
78+
print("Failed to connect to WiFi. Error:", e, "\nBoard will hard reset in 30 seconds.")
79+
time.sleep(30)
80+
microcontroller.reset()
81+
82+
# Set your Adafruit IO Username and Key in secrets.py
83+
# (visit io.adafruit.com if you need to create an account,
84+
# or if you need your Adafruit IO key.)
85+
aio_username = secrets["aio_username"]
86+
aio_key = secrets["aio_key"]
87+
88+
# Initialize an Adafruit IO HTTP API object
89+
io = IO_HTTP(aio_username, aio_key, requests)
90+
91+
# Print battery voltage to the serial console. Not necessary for Adafruit IO.
92+
print(f"Current battery voltage: {voltage:.2f}")
93+
94+
# No data has been sent yet, so the send-count is 0.
95+
alarm.sleep_memory[1] = 0
96+
97+
# Turn on the LED to indicate data is being sent.
98+
led.value = True
99+
100+
# While the switch is open...
101+
while not switch_pin.value:
102+
# Adafruit IO sending can run into issues if the network fails!
103+
# This ensures the code will continue to run.
104+
try:
105+
# Send data to Adafruit IO
106+
print("Sending new mail alert and battery voltage to Adafruit IO.")
107+
send_io_data(io.create_and_get_feed("new-mail"), "New mail!")
108+
send_io_data(io.create_and_get_feed("battery-voltage"), f"{voltage:.2f}V")
109+
print("Data sent!")
110+
if METADATA:
111+
print("Sending metadata to AdafruitIO.")
112+
# The number of times the board has awakened in the current cycle.
113+
send_io_data(io.create_and_get_feed("wake-count"), alarm.sleep_memory[0])
114+
# The number of times the mailbox/battery data has been sent.
115+
send_io_data(io.create_and_get_feed("send-count"), alarm.sleep_memory[1])
116+
# The number of Adafruit IO errors that has occurred.
117+
send_io_data(io.create_and_get_feed("error-count"), alarm.sleep_memory[2])
118+
print("Metadata sent!")
119+
time.sleep(30) # Delay included to avoid data limit throttling on Adafruit IO.
120+
alarm.sleep_memory[1] += 1 # Increment data send count by 1.
121+
led.value = False # Turn off the LED to indicate data sending is complete.
122+
123+
# Adafruit IO can fail with multiple errors depending on the situation, so this except is broad.
124+
except Exception as e: # pylint: disable=broad-except
125+
print("Failed to send to Adafruit IO. Error:", e, "\nBoard will hard reset in 30 seconds.")
126+
alarm.sleep_memory[2] += 1 # Increment error count by one.
127+
time.sleep(30)
128+
microcontroller.reset()
129+
130+
# Deinitialise the alarm pin.
131+
switch_pin.deinit()
132+
133+
# Turn off the NeoPixel/I2C power for deep sleep.
134+
power_pin = digitalio.DigitalInOut(board.NEOPIXEL_I2C_POWER)
135+
power_pin.switch_to_output(False)
136+
137+
# Turn off LED for deep sleep.
138+
led.value = False
139+
140+
# Create an alarm on pin D27.
141+
pin_alarm = alarm.pin.PinAlarm(pin=board.D27, value=False, pull=True)
142+
143+
print("Entering deep sleep.")
144+
145+
# Exit and set the alarm.
146+
alarm.exit_and_deep_sleep_until_alarms(pin_alarm)

0 commit comments

Comments
 (0)