Open
Description
CircuitPython version
Adafruit CircuitPython 9.1.0 on 2024-07-10; ESP32-S3-DevKitC-1-N32R8 with ESP32S3
Board ID:espressif_esp32s3_devkitc_1_n32r8
UID:C7FD1A1E82C7
Code/REPL
import os
import rtc
import time
import ipaddress
import wifi
import socketpool
import board
import microcontroller
import adafruit_ntp
import neopixel
import binascii
from adafruit_httpserver import Server, Request, Response, POST
#
# Global setup
#
SYSNAME = os.uname().sysname
UNIQUE_ID = binascii.hexlify(microcontroller.cpu.uid).decode('utf-8').upper()
SSID = SYSNAME + '-' + UNIQUE_ID[-4:]
led = neopixel.NeoPixel(board.IO38, 1)
led.fill(0x000000)
#
# Connect to a local WiFi access point.
# Because this code is running in a CircuitPython 9 or later environment,
# it requires a settings.toml file be created with at least the following
# six lines:
#
# AP_SSID = "WIFI SSID"
# AP_PASSWORD = "WIFI PASSWORD"
# STATIC_IP = "IP4 dotted IP address"
# GATEWAY = "192.168.0.1"
# TZ_OFFSET = -4
# DEBUG = "True"
#
# DEBUG can be either True or False.
#
wifi.radio.hostname = SSID
wifi.radio.connect(os.getenv('AP_SSID'), os.getenv('AP_PASSWORD'))
pool = socketpool.SocketPool(wifi.radio)
ntp = adafruit_ntp.NTP(pool, tz_offset = os.getenv('TZ_OFFSET'))
rtc.RTC().datetime = ntp.datetime
server = Server(pool, "/static", debug=os.getenv('DEBUG'))
def get_date():
dayname = [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",]
monthname = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December" ]
try:
now = time.localtime()
return f"{dayname[now.tm_wday]}, {now.tm_mday} {monthname[now.tm_mon-1]} {now.tm_year} - {now.tm_hour:02}:{now.tm_min:02}:{now.tm_sec:02}"
except Exception as e:
return f" >>> EXCEPTION {e}"
# The HTML page body is a Python 3 'f' string for advanced formatting.
#
# Double curly braces {{ and }} are used when HTML needs single braces for HTML
# page elements such as CSS styling.
#
def webpage():
global SSID
font_family = "sans-serif"
html = f"""
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:," />
<style>
html{{
font-family: {font_family};
background-color: #FFFFFF;
display:inline-block;
margin: 0px auto;
text-align: center;
}}
h1{{
color:#D35F8D;
word-wrap: break-word;
font-size: 35px;
}}
h2{{
color:#D35F8D;
word-wrap: break-word;
font-size: 20px;
}}
p{{
font-size: 1.5rem;
word-wrap: break-word;
}}
button{{
font-family: {font_family};
display: inline-block;
width: 99%;
border: none;
border-radius: 4px;
color: white;
padding: 16px 40px;
text-decoration: none;
font-size: 30px;
margin: 2px;
cursor: pointer;
}}
.button-red{{
background-color: #DC143C;
}}
.button-green{{
background-color: #228B22;
}}
.button-dark-gray{{
background-color: #404040;
}}
p.dotted {{
margin: auto;
width: 90%;
font-size:
25px;
text-align: center;
}}
</style>
</head>
<body>
<title>{SSID} LED Control</title>
<h1>{SSID}</h1>
<form accept-charset="utf-8" method="POST">
<button class="button-green" name="LED ON" value="ONG" type="submit">LED ON</button></a>
<button class="button-red" name="LED ON" value="ONR" type="submit">LED ON</button></a>
<button class="button-dark-gray" name="LED OFF" value="OFF" type="submit">LED OFF</button></a>
</form>
<h2>CircuitPython {os.uname().version}<br/>
{get_date()}</h2>
</body>
</html>
"""
return html
# Default route
#
@server.route("/")
def base(request: Request): # pylint: disable=unused-argument
return Response(request, webpage(), content_type='text/html')
# Determine which button was pressed and
# execute that button's associated action.
#
@server.route("/", POST)
def buttonpress(request: Request):
raw_text = request.raw_request.decode("utf8")
#print(raw_text)
#
#
if "ONG" in raw_text:
led.fill(0x006400)
#
#
if "ONR" in raw_text:
led.fill(0x640000)
#
# If the led off button was pressed...
if "OFF" in raw_text:
led.fill(0x000000)
return Response(request, webpage(), content_type='text/html')
try:
server.start(str(wifi.radio.ipv4_address))
print(f" Listening on http://{wifi.radio.ipv4_address}")
#
# If the server fails to start then reset the microprocessor.
# If there is a hardware failure then this can put the software into a
# boot loop. That's why the time.sleep(5) is there so that a Ctrl C can exit
# at the REPL during development.
#
except OSError as e:
print(f" !!! OSError: {e}")
print(" !!! OSError Exception, Waiting !!!")
time.sleep(5)
print(" !!! OSError Exception, Restarting !!!")
microcontroller.reset()
#
# DO NOT hard code the while loop as True,
# instead provide a test and exit if something goes wrong.
#
is_healthy = True;
while is_healthy:
try:
# Poll for incoming requests.
server.poll()
except Exception as e:
print(f' EXCEPTION {e}')
is_healthy = False
continue
Behavior
When left to run unattended the board will stop executing, and any attempt to perform ^D to restart returns the following message at the REPL:
Auto-reload is off.
Running in safe mode! Not running saved code.
You are in safe mode because:
Internal watchdog timer expired.
Press reset to exit safe mode.
Press any key to enter the REPL. Use CTRL-D to reload.
Description
Not only does this occur with the Espressif ESP32-S3 board, but it also occurs with the Raspberry Pi Pico and Pico/W with the same version of CircuitPython. It will also occur with CircuitPython 9.0.5, again with the boards listed above.
Additional information
No response