-
Notifications
You must be signed in to change notification settings - Fork 776
/
Copy pathcode.py
168 lines (141 loc) · 6.32 KB
/
code.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# SPDX-FileCopyrightText: 2022 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""CircuitPython WiFi Mailbox Notifier"""
import time
import ssl
import alarm
import board
import digitalio
import analogio
import wifi
import socketpool
import supervisor
import microcontroller
import adafruit_requests
from adafruit_io.adafruit_io import IO_HTTP
# Get WiFi/Adafruit IO details from secrets.py
try:
from secrets import secrets
except ImportError:
print("Please create secrets.py and add your WiFi and AIO credentials there!")
raise
# Update to True if you want metadata sent to Adafruit IO. Defaults to False.
METADATA = False
# If the reason the board started up is due to a supervisor.reload()...
if supervisor.runtime.run_reason is supervisor.RunReason.SUPERVISOR_RELOAD:
alarm.sleep_memory[3] += 1 # Increment reload number by 1.
print(f"Reload number: {alarm.sleep_memory[3]}") # Print current supervisor reload number.
if alarm.sleep_memory[3] > 5: # If supervisor reload number exceeds 5...
# Print the following...
print("Reload is not resolving the issue. \nBoard will hard reset in 20 seconds. ")
time.sleep(20) # ...wait 20 seconds...
microcontroller.reset() # ...and hard reset the board. This will clear alarm.sleep_memory.
# Initialise metadata.
if alarm.wake_alarm:
print("Awake! Alarm type:", alarm.wake_alarm)
# Increment wake count by 1.
alarm.sleep_memory[0] += 1
else:
print("Wakeup not caused by alarm.")
# Set wake count to 0.
alarm.sleep_memory[0] = 0
# Set error count to 0.
alarm.sleep_memory[2] = 0
# Print wake count to serial console.
print("Alarm wake count:", alarm.sleep_memory[0])
# No data has been sent yet, so the send-count is 0.
alarm.sleep_memory[1] = 0
# Set up battery monitoring.
voltage_pin = analogio.AnalogIn(board.VOLTAGE_MONITOR)
# Take the raw voltage pin value, and convert it to voltage.
voltage = (voltage_pin.value / 65536) * 2 * 3.3
# Set up red LED.
led = digitalio.DigitalInOut(board.LED)
led.switch_to_output()
# Set up the alarm pin.
switch_pin = digitalio.DigitalInOut(board.D27)
switch_pin.pull = digitalio.Pull.UP
# Send the data. Requires a feed name and a value to send.
def send_io_data(feed_name, value):
"""
Send data to Adafruit IO.
Provide an Adafruit IO feed name, and the value you wish to send.
"""
feed = io.create_and_get_feed(feed_name)
return io.send_data(feed["key"], value)
# Connect to WiFi
try:
wifi.radio.connect(secrets["ssid"], secrets["password"])
print("Connected to {}!".format(secrets["ssid"]))
print("IP:", wifi.radio.ipv4_address)
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
# WiFi connectivity fails with error messages, not specific errors, so this except is broad.
except Exception as error: # pylint: disable=broad-except
print("Failed to connect to WiFi. Error:", error, "\nBoard will reload in 15 seconds.")
alarm.sleep_memory[2] += 1 # Increment error count by one.
time.sleep(15)
supervisor.reload()
# Pull your Adafruit IO username and key from secrets.py
aio_username = secrets["aio_username"]
aio_key = secrets["aio_key"]
# Initialize an Adafruit IO HTTP API object
io = IO_HTTP(aio_username, aio_key, requests)
# Print battery voltage to the serial console and send it to Adafruit IO.
print(f"Current battery voltage: {voltage:.2f}V")
# Adafruit IO can run into issues if the network fails!
# This try/except ensures your code will continue to run.
try:
led.value = True # Turn on the LED to indicate data is being sent.
send_io_data("battery-voltage", f"{voltage:.2f}V")
led.value = False # Turn off the LED to indicate data sending is complete.
# Adafruit IO can fail with multiple errors depending on the situation, so this except is broad.
except Exception as error: # pylint: disable=broad-except
print("Failed to send to Adafruit IO. Error:", error, "\nBoard will reload in 15 seconds.")
alarm.sleep_memory[2] += 1 # Increment error count by one.
time.sleep(15)
supervisor.reload()
# While the door is open...
while not switch_pin.value:
# Adafruit IO sending can run into various issues which cause errors.
# This try/except ensures the code will continue to run.
try:
led.value = True # Turn on the LED to indicate data is being sent.
# Send data to Adafruit IO
print("Sending new mail alert to Adafruit IO.")
send_io_data("new-mail", "New mail!")
print("Data sent!")
# If METADATA = True at the beginning of the code, send more data.
if METADATA:
print("Sending metadata to Adafruit IO.")
# The number of times the board has awakened by an alarm since the last reset.
send_io_data("wake-count", alarm.sleep_memory[0])
# The number of times the mailbox data has been sent.
send_io_data("send-count", alarm.sleep_memory[1])
# The number of WiFi or Adafruit IO errors that have occurred.
send_io_data("error-count", alarm.sleep_memory[2])
print("Metadata sent!")
time.sleep(30) # Delay included to avoid data limit throttling on Adafruit IO.
alarm.sleep_memory[1] += 1 # Increment data send count by 1.
led.value = False # Turn off the LED to indicate data sending is complete.
# Adafruit IO can fail with multiple errors depending on the situation, so this except is broad.
except Exception as error: # pylint: disable=broad-except
print("Failed to send to Adafruit IO. Error:", error, "\nBoard will reload in 15 seconds.")
alarm.sleep_memory[2] += 1 # Increment error count by one.
time.sleep(15)
supervisor.reload()
# Deinitialise the alarm pin.
switch_pin.deinit()
# Turn off the NeoPixel/I2C power for deep sleep.
power_pin = digitalio.DigitalInOut(board.NEOPIXEL_I2C_POWER)
power_pin.switch_to_output(False)
# Turn off LED for deep sleep.
led.value = False
# Create a timer alarm to be triggered every 12 hours (43200 seconds).
time_alarm = alarm.time.TimeAlarm(monotonic_time=(time.monotonic() + 43200))
# Create a pin alarm on pin D27.
pin_alarm = alarm.pin.PinAlarm(pin=board.D27, value=False, pull=True)
print("Entering deep sleep.")
# Exit and set the alarm.
alarm.exit_and_deep_sleep_until_alarms(pin_alarm, time_alarm)