# Pico W HTTP Server with CircuitPython

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/116/437/medium800thumb/projects_demoWithHTML.jpg?1667424215)

In this guide, you'll setup an HTTP (web) server with a Pico W running CircuitPython. HTTP servers are handy for creating custom web interfaces to monitor and control IoT projects.

This example sets a static IP address for the server, logs temperature readings from a DS18B20 temperature sensor, displays server information on an OLED and serves an HTML webpage with buttons that can send HTTP POST requests to toggle pins on the Pico W.

https://youtube.com/shorts/KLYujaG7E94

The HTML webpage is included in the **code.py** file as an [f-string](https://peps.python.org/pep-0498/) so that it can take in variables directly from **code.py**. The HTML code includes buttons that send POST requests for turning the Pico W onboard LED on and off and for displaying a party parrot animation on the OLED.

![projects_edited_P1390216.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/434/medium640/projects_edited_P1390216.jpg?1667423529)

The OLED displays important information about the server. It tells you the connection status, the name of your SSID, the IP address and the current temperature reading from the DS18B20. It can also show the less important, but more fun, party parrot animation.

![projects_oledToggle.gif](https://cdn-learn.adafruit.com/assets/assets/000/116/436/medium640thumb/projects_oledToggle.jpg?1667423740)

Since the Pico W is often affectionately referred to as the Pi-Cow, a bovine-themed 3D printed case is included for this project.

![projects_edited_P1390163.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/429/medium640/projects_edited_P1390163.jpg?1667405037)

## Prerequisite Guides
[Quick-Start the Pico W WiFi with CircuitPython](https://learn.adafruit.com/pico-w-wifi-with-circuitpython/overview)
[Using DS18B20 Temperature Sensor with CircuitPython](https://learn.adafruit.com/using-ds18b20-temperature-sensor-with-circuitpython)
[Monochrome OLED Breakouts](https://learn.adafruit.com/monochrome-oled-breakouts)
## Parts
### Raspberry Pi Pico W

[Raspberry Pi Pico W](https://www.adafruit.com/product/5526)
The Raspberry Pi foundation changed single-board computing [when they released the Raspberry Pi computer](https://www.raspberrypi.org/archives/723), now they're ready to do the same for microcontrollers with the release of the brand new **Raspberry Pi Pico W**. This...

In Stock
[Buy Now](https://www.adafruit.com/product/5526)
[Related Guides to the Product](https://learn.adafruit.com/products/5526/guides)
![Angled shot of a green microcontroller with castellated pads.](https://cdn-shop.adafruit.com/640x480/5526-01.jpg)

### Fully Reversible Pink/Purple USB A to micro B Cable - 1m long

[Fully Reversible Pink/Purple USB A to micro B Cable - 1m long](https://www.adafruit.com/product/4111)
This cable is not only super-fashionable, with a woven pink and purple Blinka-like pattern, it's also fully reversible! That's right, you will save _seconds_ a day by not having to flip the cable around.

First let's talk about the cover and over-molding. We got these...

In Stock
[Buy Now](https://www.adafruit.com/product/4111)
[Related Guides to the Product](https://learn.adafruit.com/products/4111/guides)
![Fully Reversible Pink/Purple USB A to micro B Cable](https://cdn-shop.adafruit.com/640x480/4111-02.jpg)

### Monochrome 1.3" 128x64 OLED graphic display - STEMMA QT / Qwiic

[Monochrome 1.3" 128x64 OLED graphic display - STEMMA QT / Qwiic](https://www.adafruit.com/product/938)
These displays are small, only about 1.3" diagonal, but very readable due to the high contrast of an OLED display. This display is made of 128x64 individual white OLED pixels, each one is turned on or off by the controller chip. Because the display makes its own light, no backlight is...

Out of Stock
[Buy Now](https://www.adafruit.com/product/938)
[Related Guides to the Product](https://learn.adafruit.com/products/938/guides)
![Monochrome 1.3" OLED module with Adafruit logos falling like snow](https://cdn-shop.adafruit.com/product-videos/640x480/938-05.jpg)

### Waterproof 1-Wire DS18B20 Digital temperature sensor

[Waterproof 1-Wire DS18B20 Digital temperature sensor](https://www.adafruit.com/product/381)
This is a pre-wired and waterproofed (with heat shrink) version of a 1 Wire DS18B20 sensor. Handy for when you need to measure something far away, or in wet conditions. While the sensor is good up to 125°C the cable is jacketed in PVC so we suggest keeping it under 100°C. Because they...

In Stock
[Buy Now](https://www.adafruit.com/product/381)
[Related Guides to the Product](https://learn.adafruit.com/products/381/guides)
![Angled Shot of the Waterproof 1-Wire DS18B20 Digital temperature sensor.](https://cdn-shop.adafruit.com/640x480/381-01.jpg)

### Adafruit PiCowbell Proto for Pico - Reset Button & STEMMA QT

[Adafruit PiCowbell Proto for Pico - Reset Button & STEMMA QT](https://www.adafruit.com/product/5200)
Ding dong! Hear that? It's the PiCowbell ringing, letting you know that the new Adafruit&nbsp;PiCowbell Proto is finally in stock and ready to assist your [Raspberry Pi Pico](https://www.adafruit.com/product/4864) and [Pico W](https://www.adafruit.com/product/5526)...

In Stock
[Buy Now](https://www.adafruit.com/product/5200)
[Related Guides to the Product](https://learn.adafruit.com/products/5200/guides)
![Angled shot of long, skinny prototyping breakout board.](https://cdn-shop.adafruit.com/640x480/5200-00.jpg)

### STEMMA QT / Qwiic JST SH 4-pin Cable - 100mm Long

[STEMMA QT / Qwiic JST SH 4-pin Cable - 100mm Long](https://www.adafruit.com/product/4210)
This 4-wire cable is a little over 100mm / 4" long and fitted with JST-SH female 4-pin connectors on both ends. Compared with the chunkier JST-PH these are 1mm pitch instead of 2mm, but still have a nice latching feel, while being easy to insert and remove.

<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/4210)
[Related Guides to the Product](https://learn.adafruit.com/products/4210/guides)
![Angled shot of STEMMA QT / Qwiic JST SH 4-pin Cable.](https://cdn-shop.adafruit.com/640x480/4210-00.jpg)

### Part: Socket Headers for Raspberry Pi Pico
quantity: 1
2 x 20 pin Female Headers
[Socket Headers for Raspberry Pi Pico](https://www.adafruit.com/product/5583)

### Part: 0.1" male header
quantity: 1
Break-away 0.1" 36-pin strip male header
[0.1" male header](https://www.adafruit.com/product/392)

### Part: JST-PH Battery Extension Cable
quantity: 1
500mm
[JST-PH Battery Extension Cable](https://www.adafruit.com/product/1131)

### Part: 220 ohm resistors
quantity: 1
Through-Hole Resistors - 220 ohm 5% 1/4W - Pack of 25 Through-Hole Resistors - 220 ohm 5% 1/4W - Pack of 25
[220 ohm resistors](https://www.adafruit.com/product/2780)

### Part: Machine Screw and Stand-off Set – M2.5 Thread
quantity: 1
Black Nylon Machine Screw and Stand-off Set – M2.5 Thread
[Machine Screw and Stand-off Set – M2.5 Thread](https://www.adafruit.com/product/3299)

### Part: 5mm RGB Slow Blinking LED
quantity: 1
Auto changing RGB LED
[5mm RGB Slow Blinking LED](https://www.amazon.com/Multicolor-Flashing-Changing-Electronics-Components/dp/B01C19ENFA/)

### Part: M2 Brass Standoffs
quantity: 1
M2 standoffs
[M2 Brass Standoffs](https://www.amazon.com/300pcs-Standoff-Column-Spacer-Assortment/dp/B07B9X1KY6/)

# Pico W HTTP Server with CircuitPython

## Circuit Diagram

![](https://cdn-learn.adafruit.com/assets/assets/000/116/582/medium800/projects_picowHttpServer_bb.jpg?1668020381)

 **OLED**

- **OLED STEMMA QT port** to **PiCowbell STEMMA QT port**

**DS18B20**

- **Sensor GND** to **PiCowbell GND (blue wire)**
- **Sensor Data** to **PiCowbell GP6 (yellow wire)**
- **Sensor VIN** to **PiCowbell 3V (red wire)**
- **4.7K ohm resistor** between **3V and**  **GP6**

**LED for Party Parrot**

- **LED cathode** to **PiCowbell GND (black wire)**
- **LED anode** to **220 ohm resistor (white wire)**
- **220 ohm**  **resistor** to **PiCowbell**  **GP10**

## Plug in the Pico W
After wiring, plug the Pico W into the PiCowbell. The Pico W USB port should be over the PiCowbell STEMMA QT port.

![projects_picowHttpServerWithPico.png](https://cdn-learn.adafruit.com/assets/assets/000/116/384/medium640/projects_picowHttpServerWithPico.png?1667322969)

# Pico W HTTP Server with CircuitPython

## Wiring

![](https://cdn-learn.adafruit.com/assets/assets/000/116/408/medium800/projects_edited_P1390155.jpg?1667337724)

## PiCowbell Headers
Solder socket headers to the PiCowbell. You can use the Pico W as a jig to keep the headers secure.

![projects_edited_P1390086.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/406/medium640/projects_edited_P1390086.jpg?1667337706)

![projects_edited_P1390091.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/407/medium640/projects_edited_P1390091.jpg?1667337712)

## Resistors
Solder the 4.7K ohm resistor for the DS18B20 from the 3V line to GP6 on the PiCowbell. Then, solder a 220 ohm resistor from GP10 to one of the prototyping rails on the PiCowbell.

![projects_edited_P1390092.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/394/medium640/projects_edited_P1390092.jpg?1667337477)

## JST Cable
Cut the JST cable in half. Splice and tin the wires on the socket end of the cable.

![projects_edited_P1390102.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/395/medium640/projects_edited_P1390102.jpg?1667337486)

Solder the black wire of the JST cable to the GND pin on the PiCowbell. Solder the red wire of the JST cable to the prototyping rail connected to the 220 ohm resistor.

![projects_edited_P1390107.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/396/medium640/projects_edited_P1390107.jpg?1667337496)

## DS18B20
Tin the three wires of the DS18B20. Blue is ground, yellow is data and red is power.

![projects_edited_P1390115.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/397/medium640/projects_edited_P1390115.jpg?1667337506)

Solder the DS18B20 to the PiCowbell.

- **Blue wire** to **PiCowbell GND**
- **Red wire** to **PiCowbell 3V**
- **Yellow wire** to the **prototyping rail next to GP6**

![projects_edited_P1390122.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/398/medium640/projects_edited_P1390122.jpg?1667337516)

Bridge the solder joints from the 4.7K ohm resistor on GP6 to the DS18B20 yellow wire.

![projects_edited_P1390124.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/399/medium640/projects_edited_P1390124.jpg?1667337541)

That completes the PiCowbell wiring.

![projects_edited_P1390131.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/400/medium640/projects_edited_P1390131.jpg?1667337611)

## LED to JST
Take the remaining plug end of the JST cable and slip a piece of heat shrink over each of the wires.

![projects_edited_P1390133.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/401/medium640/projects_edited_P1390133.jpg?1667337620)

Solder the LED cathode to the black wire on the JST cable. Solder the LED anode to the red wire on the JST cable.

![projects_edited_P1390138.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/402/medium640/projects_edited_P1390138.jpg?1667337649)

Apply the heat shrink over the LED legs and the solder connections.

![projects_edited_P1390141.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/403/medium640/projects_edited_P1390141.jpg?1667337659)

Plug the LED JST cable into the JST socket and plug the Pico W into the PiCowbell. That completes all of the wiring!

![projects_edited_P1390143.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/404/medium640/projects_edited_P1390143.jpg?1667337671)

# Pico W HTTP Server with CircuitPython

## 3D Printing

![](https://cdn-learn.adafruit.com/assets/assets/000/116/417/medium800/projects_edited_P1390208.jpg?1667403371)

The HTTP server may be assembled with 3D printed parts, described below. The case has three lid options depending on your taste: a plain lid, a lid with a cow print or a lid with a cow face. The cow print and cow face versions of the lid can utilize the `M600` filament change command in your slicer software to accentuate the design.&nbsp;

The STL files can be downloaded directly here or from Thingiverse.

[PicoWhttpServerSTLs.zip](https://cdn-learn.adafruit.com/assets/assets/000/116/413/original/PicoWhttpServerSTLs.zip?1667402910)
[Thingiverse download](https://www.thingiverse.com/thing:5606793)
## Main Case

The main case portion needs supports for the DS18B20 temperature sensor slot. In your slicer software, you can use a **support blocker** to only add supports to the sensor slot.

![projects_supportBlockerCase2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/374/medium640/projects_supportBlockerCase2.jpg?1667322154)

![projects_supportBlockerCase.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/375/medium640/projects_supportBlockerCase.jpg?1667322167)

## Cow Print Lid

For the cow print lid, slice the model with a **0.2 mm layer height** and insert a filament change command on **layer 2**.

![projects_edited_P1390207.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/414/medium640/projects_edited_P1390207.jpg?1667403326)

![projects_lidWithCowSpots_pause2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/415/medium640/projects_lidWithCowSpots_pause2.jpg?1667403339)

## Cow Face Lid

For the cow face lid, use the **support on build plate only** option in your slicer. Slice the model with a **0.2 mm layer height** and insert filament change commands on **layers 25** , **28** and **32**.

![projects_cowSlice1.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/378/medium640/projects_cowSlice1.jpg?1667322417)

![projects_cowSlice25-28-32.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/379/medium640/projects_cowSlice25-28-32.jpg?1667322427)

The plain lid does not require any supports or filament changes. All of the lids have cutouts and mounting holes for the OLED screen and Pico W.

![projects_edited_P1390164.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/416/medium640/projects_edited_P1390164.jpg?1667403358)

# Pico W HTTP Server with CircuitPython

## Installing CircuitPython

[CircuitPython](https://github.com/adafruit/circuitpython) is a derivative of [MicroPython](https://micropython.org) designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the **CIRCUITPY** drive to iterate.

## CircuitPython Quickstart

Follow this step-by-step to quickly get CircuitPython working on your board.

[Download the latest version of CircuitPython for the Raspberry Pi Pico W from circuitpython.org](https://circuitpython.org/board/raspberry_pi_pico_w/)
 **Click the link above and download the latest UF2 file.**

Download and save it to your desktop (or wherever is handy).

![circuitpython_Cat_UF2_download.png](https://cdn-learn.adafruit.com/assets/assets/000/098/753/medium640/circuitpython_Cat_UF2_download.png?1611157944)

Start with your Pico W unplugged from USB. Hold down the **BOOTSEL** button, and while continuing to hold it (don't let go!), plug the Pico W into USB. **Continue to hold the BOOTSEL button until the RPI-RP2 drive appears!**

If the drive does not appear, unplug your Pico W and go through the above process again.

A lot of people end up using charge-only USB cables and it is very frustrating! **So make sure you have a USB cable you know is good for data sync.**

![adafruit_products_bootSel.jpg](https://cdn-learn.adafruit.com/assets/assets/000/115/887/medium640/adafruit_products_bootSel.jpg?1665763645)

You will see a new disk drive appear called **RPI-RP2**.

&nbsp;

Drag the **adafruit\_circuitpython\_etc.uf2** file to **RPI-RP2.**

![circuitpython_Cat_RPI-RP2_drive.png](https://cdn-learn.adafruit.com/assets/assets/000/098/756/medium640/circuitpython_Cat_RPI-RP2_drive.png?1611158210)

![circuitpython_Cat_drag_UF2.png](https://cdn-learn.adafruit.com/assets/assets/000/098/758/medium640/circuitpython_Cat_drag_UF2.png?1611158274)

The **RPI-RP2** drive will disappear and a new disk drive called **CIRCUITPY** will appear.

That's it, you're done! :)

![circuitpython_Cat_CIRCUITPY.png](https://cdn-learn.adafruit.com/assets/assets/000/098/759/medium640/circuitpython_Cat_CIRCUITPY.png?1611158312)

## Flash Resetting UF2

If your Pico W ever gets into a really _weird_ state and doesn't even show up as a disk drive when installing CircuitPython, try installing this 'nuke' UF2 which will do a 'deep clean' on your Flash Memory. You will lose all the files on the board, but at least you'll be able to revive it! After nuking, re-install CircuitPython

[flash_nuke.uf2](https://cdn-learn.adafruit.com/assets/assets/000/099/419/original/flash_nuke.uf2?1613329170)
# Pico W HTTP Server with CircuitPython

## Create Your settings.toml File

CircuitPython works with WiFi-capable boards to enable you to make projects that have network connectivity. This means working with various passwords and API keys. As of [CircuitPython 8](https://circuitpython.org/downloads), there is support for a **settings.toml** file. This is a file that is stored on your **CIRCUITPY** drive, that contains all of your secret network information, such as your SSID, SSID password and any API keys for IoT services. It is designed to separate your sensitive information from your **code.py** file so you are able to share your code without sharing your credentials.

CircuitPython previously used a **secrets.py** file for this purpose. The **settings.toml** file is quite similar.

Warning: Your **settings.toml** file should be stored in the main directory of your **CIRCUITPY** drive. It should not be in a folder.

## CircuitPython **settings.toml** File

This section will provide a couple of examples of what your **settings.toml** file should look like, specifically for CircuitPython WiFi projects in general.

The most minimal **settings.toml** file must contain your WiFi SSID and password, as that is the minimum required to connect to WiFi. Copy this example, paste it into your **settings.toml** , and update:

- `your_wifi_ssid`
- `your_wifi_password`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
```

Many CircuitPython network-connected projects on the Adafruit Learn System involve using Adafruit IO. For these projects, you must _also_ include your Adafruit IO username and key. Copy the following example, paste it into your settings.toml file, and update:

- `your_wifi_ssid`
- `your_wifi_password`
- `your_aio_username`
- `your_aio_key`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
ADAFRUIT_AIO_USERNAME = "your_aio_username"
ADAFRUIT_AIO_KEY = "your_aio_key"
```

Some projects use different variable names for the entries in the **settings.toml** file. For example, a project might use `ADAFRUIT_AIO_ID` in the place of `ADAFRUIT_AIO_USERNAME`. **If you run into connectivity issues, one of the first things to check is that the names in the settings.toml file match the names in the code.**

Warning: Not every project uses the same variable name for each entry in the **settings.toml** file! Always verify it matches the code.

## **settings.toml** File Tips
Here is an example **settings.toml** file.

```auto
# Comments are supported
CIRCUITPY_WIFI_SSID = "guest wifi"
CIRCUITPY_WIFI_PASSWORD = "guessable"
CIRCUITPY_WEB_API_PORT = 80
CIRCUITPY_WEB_API_PASSWORD = "passw0rd"
test_variable = "this is a test"
thumbs_up = "\U0001f44d"
```

In a **settings.toml** file, it's important to keep these factors in mind:

- Strings are wrapped in double quotes; ex: `"your-string-here"`
- Integers are _ **not** _ quoted and may be written in decimal with optional sign (`+1`, `-1`, `1000`) or hexadecimal (`0xabcd`).
  - Floats (decimal numbers), octal (`0o567`) and binary (`0b11011`) are not supported.

- Use `\u` escapes for weird characters, `\x` and `\ooo` escapes are not available in **.toml** files
  - Example: `\U0001f44d` for 👍 (thumbs up emoji) and `\u20ac` for € (EUR sign)

- Unicode emoji, and non-ASCII characters, stand for themselves as long as you're careful to save in "UTF-8 without BOM" format

&nbsp;

&nbsp;

When your&nbsp; **settings.toml&nbsp;** file is ready, you can save it in your text editor with the **.toml** &nbsp;extension.

![adafruit_products_dotToml.jpg](https://cdn-learn.adafruit.com/assets/assets/000/117/071/medium640/adafruit_products_dotToml.jpg?1671034293)

## Accessing Your **settings.toml** Information in **code.py**
In your **code.py** file, you'll need to `import` the `os` library to access the **settings.toml** file. Your settings are accessed with the `os.getenv()` function. You'll pass your settings entry to the function to import it into the **code.py** file.

```python
import os

print(os.getenv("test_variable"))
```

![](https://cdn-learn.adafruit.com/assets/assets/000/117/072/medium800/adafruit_products_tomlOutput.jpg?1671034496)

In the upcoming CircuitPython WiFi examples, you'll see how the **settings.toml&nbsp;** file is used for connecting to your SSID and accessing your API keys.

# Pico W HTTP Server with CircuitPython

## Environment Variables Docs

# Pico W HTTP Server with CircuitPython

## Code the Pico W HTTP Server

Once you've finished setting up your Pico W with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the **&nbsp;Download Project Bundle** &nbsp;button in the window below. It will download as a zipped folder.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/PicoW_CircuitPython_HTTP_Server/code.py

## Upload the Code and Libraries to the Pico W

After downloading the Project Bundle, plug your Pico W into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called&nbsp; **CIRCUITPY**. Unzip the folder and copy the following items to the Pico W's&nbsp; **CIRCUITPY** &nbsp;drive.&nbsp;

- **lib** &nbsp;folder
- **code.py**
- **partyParrots64.bmp**

Your Pico W&nbsp; **CIRCUITPY&nbsp;** drive should look like this after copying the&nbsp; **lib** &nbsp;folder, **partyParrots64.bmp** file and the&nbsp; **code.py&nbsp;** file.

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/PicoW_CircuitPython_HTTP_Server.png )

## Add Your&nbsp; **settings.toml** &nbsp;File

As of CircuitPython 8.0.0, there is support for&nbsp;[Environment Variables](https://docs.circuitpython.org/en/latest/docs/environment.html). Environment variables are stored in a&nbsp; **settings.toml** &nbsp;file. Similar to&nbsp; **secrets.py** , the&nbsp; **settings.toml&nbsp;** file separates your sensitive information from your main&nbsp; **code.py** &nbsp;file. Add your&nbsp; **settings.toml** &nbsp;file as described in the&nbsp;[Create Your settings.toml File page](https://learn.adafruit.com/pico-w-http-server-with-circuitpython/create-your-settings-toml-file)&nbsp;earlier in this guide. You'll need to include your&nbsp;`CIRCUITPY_WIFI_SSID`&nbsp;and&nbsp;`CIRCUITPY_WIFI_PASSWORD`.

```auto
CIRCUITPY_WIFI_SSID = "your-ssid-here"
CIRCUITPY_WIFI_PASSWORD = "your-ssid-password-here"
```

## How the CircuitPython Code Works
The code begins by setting up the onboard LED, LED connected to pin `GP10` and the `OneWireBus` for the DS18B20 sensor.

```python
#  onboard LED setup
led = DigitalInOut(board.LED)
led.direction = Direction.OUTPUT
led.value = False

#  pin used for party parrot animation
parrot_pin = DigitalInOut(board.GP10)
parrot_pin.direction = Direction.OUTPUT
parrot_pin.value = False

# one-wire bus for DS18B20
ow_bus = OneWireBus(board.GP6)

# scan for temp sensor
ds18 = DS18X20(ow_bus, ow_bus.scan()[0])
```

## Convert Celsius to Fahrenheit
The function `c_to_f()` converts Celsius temperature readings to Fahrenheit.&nbsp;

```python
#  function to convert celcius to fahrenheit
def c_to_f(temp):
    temp_f = (temp * 9/5) + 32
    return temp_f
```

## OLED Setup
The I2C OLED is instantiated over I2C with the PiCowbell's STEMMA QT port pins (`GP4` and `GP5`).&nbsp;

```python
# STEMMA I2C on picowbell
i2c = busio.I2C(board.GP5, board.GP4)
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3D, reset=oled_reset)

WIDTH = 128
HEIGHT = 64
offset_y = 5

display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=WIDTH, height=HEIGHT)

# default display group
splash = displayio.Group()
display.root_group = splash
```

## Static IP and Connect to WiFi
As the network connection is established, the text "`Connecting...`" is shown on the I2C display. First, a static IP address is set with `set_ipv4_address()`. You can edit the IP address `ipv4` to change to the IP address of your choice. By default, it is `192.168.1.42`.

Then, the Pico W connects to your SSID by accessing your SSID and SSID password in your **.env** file.&nbsp;

```python
#  connect to network
print()
print("Connecting to WiFi")
connect_text = "Connecting..."
connect_text_area = label.Label(
    terminalio.FONT, text=connect_text, color=0xFFFFFF, x=0, y=offset_y
)
splash.append(connect_text_area)

#  set static IP address
ipv4 =  ipaddress.IPv4Address("192.168.1.42")
netmask =  ipaddress.IPv4Address("255.255.255.0")
gateway =  ipaddress.IPv4Address("192.168.1.1")
wifi.radio.set_ipv4_address(ipv4=ipv4,netmask=netmask,gateway=gateway)
#  connect to your SSID
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))

print("Connected to WiFi")
pool = socketpool.SocketPool(wifi.radio)
server = Server(pool, "/static", debug=True)
```

## HTML Variables
A few variables are created for the HTML script. The HTML is passed as an [f-string](https://docs.python.org/3/tutorial/inputoutput.html), so variables from **code.py** can be included. `temp_test` holds the temperature reading from the DS18B20. You can adjust this to utilize either Celsius or Fahrenheit.

`font_family` is the font used for the CSS styling. You can change this to your preferred CSS font.

```python
#  variables for HTML
#  comment/uncomment desired temp unit

#  temp_test = str(ds18.temperature)
#  unit = "C"
temp_test = str(c_to_f(ds18.temperature))
unit = "F"
#  font for HTML
font_family = "monospace"
```

## HTML Code as a String
The HTML code is passed as an f-string in the `webpage()` function. The function returns a string that can be passed with `HTTPResponse` on a `@server.route()` function.

It's important to note that by using this method, you need to use double curly brackets (`{{` and `}}`) if something in the HTML code _actually_ needs to be inside curly brackets, such as certain parts of CSS style formatting.

```python
#  the HTML script
#  setup as an f string
#  this way, can insert string variables from code.py directly
#  of note, use {{ and }} if something from html *actually* needs to be in brackets
#  i.e. CSS style formatting
def webpage():
    html = f"""
    &lt;!DOCTYPE html&gt;
    &lt;html&gt;
    &lt;head&gt;
    &lt;meta http-equiv="Content-type" content="text/html;charset=utf-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    &lt;style&gt;
    html{{font-family: {font_family}; background-color: lightgrey;
    display:inline-block; margin: 0px auto; text-align: center;}}
      h1{{color: deeppink; padding: 2vh; font-size: 35px;}}
      p{{font-size: 1.5rem;}}
      .button{{font-family: {font_family};display: inline-block;
      background-color: black; border: none;
      border-radius: 4px; color: white; padding: 16px 40px;
      text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}}
      p.dotted {{margin: auto; height: 50px;
      width: 75%; font-size: 25px; text-align: center;}}
    &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;title&gt;Pico W HTTP Server&lt;/title&gt;
    &lt;h1&gt;Pico W HTTP Server&lt;/h1&gt;
    &lt;p class="dotted"&gt;This is a Pico W running an HTTP server with CircuitPython.&lt;/p&gt;
    &lt;p class="dotted"&gt;The current ambient temperature near the Pico W is 
    &lt;span style="color: deeppink;"&gt;{temp_test}°{unit}&lt;/span&gt;&lt;/p&gt;
    &lt;h1&gt;Control the LED on the Pico W with these buttons:&lt;/h1&gt;
    &lt;form accept-charset="utf-8" method="POST"&gt;
    &lt;button class="button" name="LED ON" value="ON" type="submit"&gt;LED ON&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;&lt;/form&gt;
    &lt;p&gt;&lt;form accept-charset="utf-8" method="POST"&gt;
    &lt;button class="button" name="LED OFF" value="OFF" type="submit"&gt;LED OFF&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;&lt;/form&gt;
    &lt;h1&gt;Party?&lt;/h&gt;
    &lt;p&gt;&lt;form accept-charset="utf-8" method="POST"&gt;
    &lt;button class="button" name="party" type="submit"&gt;PARTY!&lt;/button&gt;&lt;/a&gt;&lt;/p&gt;&lt;/form&gt;
    &lt;/body&gt;&lt;/html&gt;
    """
    return html
```

## Server Routing and POST Requests
When the static IP address is accessed, the server serves the HTML code in `webpage()` with `Response()`. The `content_type` needs to be defined as `"text/html"`.

The other routing option occurs when an HTTP POST request is sent to the server. When a POST request comes in, the text is decoded into `raw_text`. POST requests are sent when the buttons are pressed on the HTML site.

The buttons have names and values defined in the HTML code that are sent as a part of the POST request. When the POST request contains `"ON"`, that means that the LED ON button was pressed on the site and the onboard LED on the Pico W is turned on. When a POST request contains `"OFF"`, that means that the LED OFF button was pressed on the site and the onboard LED on the Pico W is turned off. Finally, when a POST request contains `"party"`, it means that the PARTY! button was pressed on the site and the `party_pin` is toggled.

```python
#  route default static IP
@server.route("/")
def base(request: Request):  # pylint: disable=unused-argument
    #  serve the HTML f string
    #  with content type text/html
    return Response(request, f"{webpage()}", content_type='text/html')

#  if a button is pressed on the site
@server.route("/", POST)
def buttonpress(request: Request):
    #  get the raw text
    raw_text = request.raw_request.decode("utf8")
    print(raw_text)
    #  if the led on button was pressed
    if "ON" in raw_text:
        #  turn on the onboard LED
        led.value = True
    #  if the led off button was pressed
    if "OFF" in raw_text:
        #  turn the onboard LED off
        led.value = False
    #  if the party button was pressed
    if "party" in raw_text:
        #  toggle the parrot_pin value
        parrot_pin.value = not parrot_pin.value
    #  reload site
    return Response(request, f"{webpage()}", content_type='text/html')
```

## Start the Server
The server starts up on the static IP address with `server.start()`. This is wrapped in a `try/except` statement in case of an `OSError`, causing the server to be unable to start. If this occurs, then the Pico W is reset with `microcontroller.reset()`.

After the server has started up successfully, the text on the OLED is updated to say that it is connected along with your SSID name, IP address and the temperature reading from the DS18B20.

```python
print("starting server..")
# startup the server
try:
    server.start(str(wifi.radio.ipv4_address))
    print("Listening on http://%s:80" % wifi.radio.ipv4_address)
#  if the server fails to begin, restart the pico w
except OSError:
    time.sleep(5)
    print("restarting..")
    microcontroller.reset()
ping_address = ipaddress.ip_address("8.8.4.4")

#  text objects for screen
#  connected to SSID text
connect_text_area.text = "Connected to:"
ssid_text = "%s" % os.getenv('WIFI_SSID')
ssid_text_area = label.Label(
    terminalio.FONT, text=ssid_text, color=0xFFFFFF, x=0, y=offset_y+15
)
splash.append(ssid_text_area)

#  display ip address
ip_text = "IP: %s" % wifi.radio.ipv4_address
ip_text_area = label.Label(
    terminalio.FONT, text=ip_text, color=0xFFFFFF, x=0, y=offset_y+30
)
splash.append(ip_text_area)
#  display temp reading
temp_text = "Temperature: %.02f F" % float(temp_test)
temp_text_area = label.Label(
    terminalio.FONT, text=temp_text, color=0xFFFFFF, x=0, y=offset_y+45
)
splash.append(temp_text_area)
```

## Party Parrot Tilegrid
There is a party parrot sprite sheet that is shown as an animated sprite sequence when the PARTY! button is pressed on the HTML site. The sprite sheet is added to a second `displayio.Group()` called `parrot_group`. This lets you display either the default `splash` group with the server information text or the party parrot sprite sheet with `parrot_group`.

```python
#  party parrot display group
parrot_group = displayio.Group()
#  load in party parrot bitmap
parrot_bit, parrot_pal = adafruit_imageload.load("/partyParrots64.bmp",
                                                 bitmap=displayio.Bitmap,
                                                 palette=displayio.Palette)
parrot_grid = displayio.TileGrid(parrot_bit, pixel_shader=parrot_pal,
                                 width=1, height=1,
                                 tile_height=64, tile_width=64,
                                 default_tile=1,
                                 x=32, y=0)
parrot_group.append(parrot_grid)
```

## Variables
The last portion before the loop are some variables. `clock` is a `time.monotonic()` device that will be used for timekeeping. `parrot` is a state machine to track if the party parrot animation should be playing. `party` is a `time.monotonic()` device for showing the party parrot animation and `p` is the variable for the party parrot tilegrid index.

```python
clock = time.monotonic() #  time.monotonic() holder for server ping
parrot = False #  parrot state
party = 0 #  time.monotonic() holder for party parrot
p = 0 #  index for tilegrid
```

## The Loop
In the loop, every 30 seconds, the Pico W sends out a ping to check the connection status. If the ping is not returned, then the OLED text is updated to `Disconnected!`. If a ping is returned, then the text remains as `Connected to:` with your SSID name. Additionally, the temperature reading from the DS18B20 is taken, updating the OLED text entry and the entry for the HTML f string.

```python
while True:
    try:
        #  every 30 seconds, ping server &amp; update temp reading
        if (clock + 30) &lt; time.monotonic():
            if wifi.radio.ping(ping_address) is None:
                connect_text_area.text = "Disconnected!"
                ssid_text_area.text = None
                print("lost connection")
            else:
                connect_text_area.text = "Connected to:"
                ssid_text_area.text = "%s" % os.getenv('WIFI_SSID')
                print("connected")
            clock = time.monotonic()
            #  comment/uncomment for desired units
            #  temp_test = str(ds18.temperature)
            temp_test = str(c_to_f(ds18.temperature))
            temp_text_area.text = "Temperature: %d F" % temp_test
```

## Party Parrot Animation
If the `parrot_pin.value` is toggled to `True` by the PARTY! button on the HTML site, then the OLED shows the `parrot_group` tilegrid for the party parrot sprite sheet. Every `0.1` seconds, the tilegrid is advanced by `1` to play the animation. When the pin is toggled to `False`, then the display shows the `splash` group, displaying the server information.

```python
#if parrot is True:
        if parrot_pin.value is True:
            #  switch to party parrot display group
            display.root_group = parrot_group
            if (party + 0.1) &lt; time.monotonic():
                #  the party parrot animation cycles
                parrot_grid[0] = p
                #  p is the tilegrid index location
                p = (p + 1) % 10
                party = time.monotonic()
        #  if it isn't a party
        else:
            #  show default display with info
            display.root_group = splash
```

## Poll the Server
The final, and most important, part of the loop is `server.poll()`. This function polls the server for incoming and outgoing requests from both **code.py** and the HTML site.

```python
#  poll the server for incoming/outgoing requests
server.poll()
```

# Pico W HTTP Server with CircuitPython

## Assembly

![](https://cdn-learn.adafruit.com/assets/assets/000/116/418/medium800/projects_edited_P1390174.jpg?1667404143)

Attach four M2 standoffs to the Pico W's four mounting holes with M2 nuts.

![projects_edited_P1390176.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/419/medium640/projects_edited_P1390176.jpg?1667404833)

Attach the Pico W to the case lid with four M2 screws.

![projects_edited_P1390182.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/420/medium640/projects_edited_P1390182.jpg?1667404842)

![projects_edited_P1390184.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/421/medium640/projects_edited_P1390184.jpg?1667404851)

Attach the OLED screen with four M2.5 screws and nuts.

![projects_edited_P1390186.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/422/medium640/projects_edited_P1390186.jpg?1667404861)

![projects_edited_P1390188.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/423/medium640/projects_edited_P1390188.jpg?1667404868)

Plug the PiCowbell into the Pico W. The STEMMA port on the PiCowbell should be below the USB port on the Pico W.

![projects_edited_P1390191.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/424/medium640/projects_edited_P1390191.jpg?1667404879)

Connect the OLED to the STEMMA port on the PiCowbell with a STEMMA QT cable.

![projects_edited_P1390193.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/425/medium640/projects_edited_P1390193.jpg?1667404890)

Route the DS18B20 through the larger opening in the case. Slide the sensor through the clip on the top of the case.

![projects_edited_P1390197.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/426/medium640/projects_edited_P1390197.jpg?1667404900)

Wrap the excess cable for the DS18B20 into the bottom of the case. Route the LED through the larger side opening.

![projects_edited_P1390200.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/427/medium640/projects_edited_P1390200.jpg?1667404910)

Close the case with the lid. Mount the LED into the mounting hole on the lid in the cow's bell.

![projects_edited_P1390202.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/428/medium640/projects_edited_P1390202.jpg?1667404922)

# Pico W HTTP Server with CircuitPython

## Usage

![](https://cdn-learn.adafruit.com/assets/assets/000/116/439/medium800/projects_edited_P1390212.jpg?1667424821)

After powering up your Pico W, your server will begin running on your static IP address. Access your HTML webpage by **opening a browser** and **navigating to the IP address**. You can confirm your IP address by checking the OLED connected to the Pico W.

You should see your HTML code displayed in your browser window. The temperature reading from the DS18B20 will be shown towards the top of the screen.

![projects_server.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/430/medium640/projects_server.jpg?1667405124)

Click the LED ON and LED OFF buttons on the webpage to turn the Pico W's onboard LED on and off.

![projects_ledDemo.gif](https://cdn-learn.adafruit.com/assets/assets/000/116/440/medium640thumb/projects_ledDemo.jpg?1667425069)

Click the PARTY! button on the webpage to start and stop the party parrot animation on the OLED. The slow change RGB LED will also turn on and off.

![projects_partyClose.gif](https://cdn-learn.adafruit.com/assets/assets/000/116/438/medium640thumb/projects_partyClose.jpg?1667424774)

## Going Further
You can adapt this code to suit your project needs. You can change the look of the HTML page by changing the CSS styling or change the CircuitPython portion to control a relay or log multiple sensors around your home. For more information on the CircuitPython HTTPServer library, be sure to check out the [library documentation on Read the Docs](https://docs.circuitpython.org/projects/httpserver/en/latest/).

[ Adafruit CircuitPython HTTPServer Library Documentation](https://docs.circuitpython.org/projects/httpserver/en/latest/)

## Featured Products

### Raspberry Pi Pico W

[Raspberry Pi Pico W](https://www.adafruit.com/product/5526)
The Raspberry Pi foundation changed single-board computing [when they released the Raspberry Pi computer](https://www.raspberrypi.org/archives/723), now they're ready to do the same for microcontrollers with the release of the brand new **Raspberry Pi Pico W**. This...

In Stock
[Buy Now](https://www.adafruit.com/product/5526)
[Related Guides to the Product](https://learn.adafruit.com/products/5526/guides)
### Fully Reversible Pink/Purple USB A to micro B Cable - 1m long

[Fully Reversible Pink/Purple USB A to micro B Cable - 1m long](https://www.adafruit.com/product/4111)
This cable is not only super-fashionable, with a woven pink and purple Blinka-like pattern, it's also fully reversible! That's right, you will save _seconds_ a day by not having to flip the cable around.

First let's talk about the cover and over-molding. We got these...

In Stock
[Buy Now](https://www.adafruit.com/product/4111)
[Related Guides to the Product](https://learn.adafruit.com/products/4111/guides)
### Monochrome 1.3" 128x64 OLED graphic display - STEMMA QT / Qwiic

[Monochrome 1.3" 128x64 OLED graphic display - STEMMA QT / Qwiic](https://www.adafruit.com/product/938)
These displays are small, only about 1.3" diagonal, but very readable due to the high contrast of an OLED display. This display is made of 128x64 individual white OLED pixels, each one is turned on or off by the controller chip. Because the display makes its own light, no backlight is...

Out of Stock
[Buy Now](https://www.adafruit.com/product/938)
[Related Guides to the Product](https://learn.adafruit.com/products/938/guides)
### Waterproof 1-Wire DS18B20 Digital temperature sensor

[Waterproof 1-Wire DS18B20 Digital temperature sensor](https://www.adafruit.com/product/381)
This is a pre-wired and waterproofed (with heat shrink) version of a 1 Wire DS18B20 sensor. Handy for when you need to measure something far away, or in wet conditions. While the sensor is good up to 125°C the cable is jacketed in PVC so we suggest keeping it under 100°C. Because they...

In Stock
[Buy Now](https://www.adafruit.com/product/381)
[Related Guides to the Product](https://learn.adafruit.com/products/381/guides)
### Adafruit PiCowbell Proto for Pico - Reset Button & STEMMA QT

[Adafruit PiCowbell Proto for Pico - Reset Button & STEMMA QT](https://www.adafruit.com/product/5200)
Ding dong! Hear that? It's the PiCowbell ringing, letting you know that the new Adafruit&nbsp;PiCowbell Proto is finally in stock and ready to assist your [Raspberry Pi Pico](https://www.adafruit.com/product/4864) and [Pico W](https://www.adafruit.com/product/5526)...

In Stock
[Buy Now](https://www.adafruit.com/product/5200)
[Related Guides to the Product](https://learn.adafruit.com/products/5200/guides)
### STEMMA QT / Qwiic JST SH 4-pin Cable - 100mm Long

[STEMMA QT / Qwiic JST SH 4-pin Cable - 100mm Long](https://www.adafruit.com/product/4210)
This 4-wire cable is a little over 100mm / 4" long and fitted with JST-SH female 4-pin connectors on both ends. Compared with the chunkier JST-PH these are 1mm pitch instead of 2mm, but still have a nice latching feel, while being easy to insert and remove.

<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/4210)
[Related Guides to the Product](https://learn.adafruit.com/products/4210/guides)
### Socket Headers for Raspberry Pi Pico - 2 x 20 pin Female Headers

[Socket Headers for Raspberry Pi Pico - 2 x 20 pin Female Headers](https://www.adafruit.com/product/5583)
These&nbsp; **Socket Headers** &nbsp;alone are, well, lonely. But pair them with the&nbsp;[Raspberry Pi Pico](https://www.adafruit.com/category/875), and you're in business!

Socket headers are like the duct tape of electronics. They're great for connecting...

In Stock
[Buy Now](https://www.adafruit.com/product/5583)
[Related Guides to the Product](https://learn.adafruit.com/products/5583/guides)
### Break-away 0.1" 36-pin strip male header - Black - 10 pack

[Break-away 0.1" 36-pin strip male header - Black - 10 pack](https://www.adafruit.com/product/392)
Breakaway header is like the duct tape of electronics. It's great for connecting things together, soldering to perf-boards, fits into any breakout or breadboard, etc. We go through these guys real fast, and thought that given how handy they are, we'd offer them in a pack of ten!<br...></br...>

In Stock
[Buy Now](https://www.adafruit.com/product/392)
[Related Guides to the Product](https://learn.adafruit.com/products/392/guides)

## Related Guides

- [Adafruit PiCowbell Proto for Pico](https://learn.adafruit.com/picowbell-proto.md)
- [Faderwave Synthesizer](https://learn.adafruit.com/faderwave-synthesizer.md)
- [NeoPixel Mini VU Meter](https://learn.adafruit.com/neopixel-mini-vu-meter.md)
- [HalloWing Magic 9 Ball](https://learn.adafruit.com/hallowing-magic-9-ball.md)
- [3D Printed Case for Adafruit Feather](https://learn.adafruit.com/3d-printed-case-for-adafruit-feather.md)
- [Pi SSD Media Server](https://learn.adafruit.com/pi-ssd-media-server.md)
- [GEMMA M0 Case](https://learn.adafruit.com/gemma-m0-case.md)
- [Raspberry Pi Zero Stand](https://learn.adafruit.com/raspberry-pi-zero-stand.md)
- [USB C Power Delivery Monitor](https://learn.adafruit.com/usb-c-benchtop-power-supply.md)
- [RP2040 RunCPM Emulator with USB Keyboard & HDMI screen](https://learn.adafruit.com/rp2040-runcpm-emulator-with-usb-keyboard-hdmi-screen.md)
- [Tyrell Desktop Synthesizer](https://learn.adafruit.com/tyrell-desktop-synthesizer.md)
- [16x16 NeoPixel Matrix Square Pixel Display](https://learn.adafruit.com/16x16-neopixel-matrix-square-pixel-display.md)
- [CircuitPython OLED and Dual Knob Sketcher](https://learn.adafruit.com/circuitpython-oled-knob-sketcher.md)
- [NFC Raspberry Pi Media Player](https://learn.adafruit.com/nfc-raspberry-pi-media-player.md)
- [reef-pi Guide 2: Power Controller](https://learn.adafruit.com/reef-pi-power-controller.md)
- [3D Printed Frame for Adafruit IS31FL3741 LED Glasses](https://learn.adafruit.com/3d-printed-frame-for-led-glasses-is31fl3741.md)
