Hi,
I am using a pico webserver for easy configuration of wifi credentials. When the pico has connected to the web i want the pico to connect to anvil via uplink. I cannot get this to work as the script seems to stop when the webserver run. Do you have any ideas for improvements ?
See code from Pico below
Code Sample:
from phew import access_point, connect_to_wifi, is_connected_to_wifi, dns, server
from phew.template import render_template
import json
import machine
import os
import utime
import _thread
import anvil.pico
from machine import Pin, reset
from utime import sleep
import uasyncio
import network
AP_NAME = "pi pico"
AP_DOMAIN = "pipico.net"
AP_TEMPLATE_PATH = "ap_templates"
APP_TEMPLATE_PATH = "app_templates"
WIFI_FILE = "wifi.json"
WIFI_MAX_ATTEMPTS = 3
def machine_reset():
utime.sleep(1)
print("Resetting...")
machine.reset()
def setup_mode():
print("Entering setup mode...")
def ap_index(request):
if request.headers.get("host").lower() != AP_DOMAIN.lower():
return render_template(f"{AP_TEMPLATE_PATH}/redirect.html", domain=AP_DOMAIN.lower())
return render_template(f"{AP_TEMPLATE_PATH}/index.html")
def ap_configure(request):
print("Saving wifi credentials...")
# Get the values from the form input fields
ssid = request.form["ssid"]
password = request.form["password"]
email = request.form["email"]
id = request.form["id"]
# Create a dictionary to store the values
wifi_data = {
"ssid": ssid,
"password": password,
"email": email,
"id": id
}
with open(WIFI_FILE, "w") as f:
json.dump(wifi_data, f)
f.close()
# Reboot from a new thread after responding to the user.
_thread.start_new_thread(machine_reset, ())
return render_template(f"{AP_TEMPLATE_PATH}/configured.html", ssid=ssid)
def ap_catch_all(request):
if request.headers.get("host") != AP_DOMAIN:
return render_template(f"{AP_TEMPLATE_PATH}/redirect.html", domain=AP_DOMAIN)
return "Not found.", 404
server.add_route("/", handler=ap_index, methods=["GET"])
server.add_route("/configure", handler=ap_configure, methods=["POST"])
server.set_callback(ap_catch_all)
ap = access_point(AP_NAME)
ip = ap.ifconfig()[0]
dns.run_catchall(ip)
def application_mode():
print("Entering application mode.")
onboard_led = machine.Pin("LED", machine.Pin.OUT)
def app_index(request):
return render_template(f"{APP_TEMPLATE_PATH}/index.html")
def app_toggle_led(request):
onboard_led.toggle()
return "OK"
def app_get_temperature(request):
# Not particularly reliable but uses built-in hardware.
# Demos how to incorporate sensor data into this application.
# The front end polls this route and displays the output.
# Replace code here with something else for a 'real' sensor.
# Algorithm used here is from:
# https://www.coderdojotc.org/micropython/advanced-labs/03-internal-temperature/
sensor_temp = machine.ADC(4)
reading = sensor_temp.read_u16() * (3.3 / (65535))
temperature = 27 - (reading - 0.706) / 0.001721
return f"{round(temperature, 1)}"
def app_reset(request):
# Deleting the WIFI configuration file will cause the device to reboot as
# the access point and request new configuration.
os.remove(WIFI_FILE)
# Reboot from a new thread after responding to the user.
_thread.start_new_thread(machine_reset, ())
return render_template(f"{APP_TEMPLATE_PATH}/reset.html", access_point_ssid=AP_NAME)
def app_catch_all(request):
return "Not found.", 404
server.add_route("/", handler=app_index, methods=["GET"])
server.add_route("/toggle", handler=app_toggle_led, methods=["GET"])
server.add_route("/temperature", handler=app_get_temperature, methods=["GET"])
server.add_route("/reset", handler=app_reset, methods=["GET"])
# Add other routes for your application...
server.set_callback(app_catch_all)
# Figure out which mode to start up in...
try:
os.stat(WIFI_FILE)
# File was found, attempt to connect to wifi...
with open(WIFI_FILE) as f:
wifi_current_attempt = 1
wifi_credentials = json.load(f)
while wifi_current_attempt < WIFI_MAX_ATTEMPTS:
ip_address = connect_to_wifi(wifi_credentials["ssid"], wifi_credentials["password"])
if is_connected_to_wifi():
print(f"Connected to wifi, IP address {ip_address}")
break
else:
wifi_current_attempt += 1
if is_connected_to_wifi():
application_mode()
else:
# Bad configuration, delete the credentials file, reboot
# into setup mode to get new credentials from the user.
print("Bad wifi connection!")
print(wifi_credentials)
os.remove(WIFI_FILE)
machine_reset()
except Exception:
# Either no wifi configuration file found, or something went wrong,
# so go into setup mode.
setup_mode()
print("before webserver")
def webserver():
# Start the web server...
server.run()
webserver()
#webserver()
print("afterwebserver")
# This is an example Anvil Uplink script for the Pico W.
# See https://anvil.works/pico for more information
UPLINK_KEY = "******"
#generate unique device ID from anvil app and set it here
DEVICE_ID = "278960A602"
# We use the LED to indicate server calls and responses.
led = Pin(26, Pin.OUT) # Create LED object from Pin 26, Set Pin 26 to output
LED_STATUS = ""
@anvil.pico.callable_async("get_led_status_"+DEVICE_ID)
async def get_led_status():
return LED_STATUS
@anvil.pico.callable_async("useremail_"+DEVICE_ID)
async def useremail():
email = "******"
print(email)
return email
@anvil.pico.callable_async("systemon_"+DEVICE_ID)
async def systemon():
global LED_STATUS
led.value(1) # Set led turn on
LED_STATUS = "ON"
print("LED is ON")
return "LED is ON"
@anvil.pico.callable_async("systemoff_"+DEVICE_ID)
async def systemoff():
global LED_STATUS
led.value(0) # Set led turn off
LED_STATUS = "OFF"
print("LED is OFF")
return "LED is OFF"
sleep(5)
# Connect the Anvil Uplink. In MicroPython, this call will block forever.
anvil.pico.connect(UPLINK_KEY)
#anvil.pico.connect(UPLINK_KEY,on_first_connect=webserver())