v1 Web interface:

Example GPT Response from the API:

Code: (Be sure to replace your SSID, Password, And OpenAPI/WeatherAPI Keys!)

import network
import socket
import urequests
import time
import dht
import machine
import ntptime
from machine import Pin
import ujson

def debug_print(*args, **kwargs):
    print("[DEBUG]", *args, **kwargs)

# Replace with your network credentials
SSID = "your_SSID"
PASSWORD = "your_PASSWORD"

# OpenAI API Key and OpenWeatherMap API Key
OPENAI_API_KEY = "your_API_KEY"
WEATHER_API_KEY = "your_WEATHER_API_KEY"
zip_code = "10001"  # Default zip code

# Toggle for DHT sensor
USE_DHT_SENSOR = False

# DHT sensor settings
if USE_DHT_SENSOR:
    dht_pin = Pin(15)
    dht_sensor = dht.DHT11(dht_pin)

# Connect to WiFi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)

while not wlan.isconnected():
    time.sleep(1)
    debug_print("Connecting to WiFi...")

debug_print("Connected to WiFi")

# Synchronize time using NTP
def synchronize_time():
    try:
        ntptime.settime()
        debug_print("Time synchronized")
    except Exception as e:
        debug_print("Failed to synchronize time:", e)

synchronize_time()

# Function to get current time
def get_current_time():
    t = time.localtime(time.time() + 3600 * -4)  # Adjust for your timezone
    return "{}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(t[0], t[1], t[2], t[3], t[4], t[5])

# Function to get weather data
def get_weather_data(zip_code):
    url = f"http://api.openweathermap.org/data/2.5/weather?zip={zip_code},us&appid={WEATHER_API_KEY}&units=metric"
    response = urequests.get(url)
    if response.status_code == 200:
        data = response.json()
        temp = data['main']['temp']
        description = data['weather'][0]['description']
        return f"{temp}°C, {description}"
    else:
        return "Unable to get weather data"

# Function to decode URL parameters
def url_decode(s):
    s = s.replace('+', ' ')
    parts = s.split('%')
    res = parts[0]
    for part in parts[1:]:
        if len(part) >= 2:
            res += chr(int(part[:2], 16)) + part[2:]
        else:
            res += '%' + part
    return res

# Function to parse query parameters
def parse_query_params(query):
    params = {}
    if '?' in query:
        query = query.split('?')[1]
        for param in query.split('&'):
            if '=' in param:
                key, value = param.split('=')
                params[key] = url_decode(value)
    return params

def test_request():
    try:
        response = urequests.get('http://httpbin.org/get')
        debug_print("Test request status:", response.status_code)
        debug_print("Test request content:", response.text)
    except Exception as e:
        debug_print("Test request failed:", str(e))

# Call this function before your main loop
test_request()

# Function to handle HTTP requests
def handle_request(request):
    global zip_code
    try:
        if not request:
            debug_print("Received empty request")
            return "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\nEmpty request received"

        request = request.decode('utf-8')
        request_line = request.split('\r\n')[0]
        parts = request_line.split(' ')
        if len(parts) < 2:
            debug_print(f"Invalid request line: {request_line}")
            return "HTTP/1.1 400 Bad Request\r\nContent-Type: text/html\r\n\r\nInvalid request format"

        method, path = parts[:2]

        query_params = parse_query_params(path)

        if path.startswith('/ask'):
            question = query_params.get('question', '')

            # Prepare the message
            message = ""

            # Read sensor data if enabled
            if USE_DHT_SENSOR:
                dht_sensor.measure()
                temp = dht_sensor.temperature()
                hum = dht_sensor.humidity()
                message += f"The current temperature is {temp}°C and humidity is {hum}%. "
            else:
                message += "DHT sensor is not enabled. "

            # Get current time
            current_time = get_current_time()
            message += f"The current time is {current_time}. "

            # Get current weather data
            weather = get_weather_data(zip_code)
            message += f"Current weather: {weather}. "

            # Add user question to the message
            message += f"User question: {question}"

            payload = ujson.dumps({
                "model": "gpt-3.5-turbo",
                "messages": [{"role": "user", "content": message}]
            }).encode('utf-8')

            headers = {
                'Content-Type': 'application/json',
                'Authorization': f'Bearer {OPENAI_API_KEY}'
            }

            try:
                debug_print("Payload:", payload)
                debug_print("Headers:", headers)

                response = urequests.post(
                    "https://api.openai.com/v1/chat/completions",
                    headers=headers,
                    data=payload
                )
                debug_print("Response status:", response.status_code)
                debug_print("Response content:", response.text)
                
                if response.status_code == 200:
                    chat_response = response.json()['choices'][0]['message']['content']
                else:
                    chat_response = f"Error communicating with ChatGPT: {response.status_code} {response.text}"
                    debug_print(chat_response)
            except Exception as e:
                chat_response = f"Exception during communication: {str(e)}"
                debug_print(chat_response)

            return f"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n{chat_response}"

        elif path.startswith('/setzip'):
            zip_code = query_params.get('zipcode', zip_code)
            return f"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nZip code set to {zip_code}"

        else:
            return """HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n
            <html>
            <body>
            <h1>Raspberry Pi Pico W Chat with ChatGPT</h1>
            <form action="/ask" method="get">
                <input type="text" name="question" placeholder="Ask ChatGPT...">
                <input type="submit" value="Send">
            </form>
            <form action="/setzip" method="get">
                <input type="text" name="zipcode" placeholder="Enter your zip code...">
                <input type="submit" value="Set Zip Code">
            </form>
            </body>
            </html>
            """
    except Exception as e:
        debug_print(f"Error in handle_request: {str(e)}")
        return "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/html\r\n\r\nAn error occurred while processing your request."

# Create a socket and listen for incoming connections
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
debug_print("Listening on", addr)

while True:
    try:
        cl, addr = s.accept()
        debug_print('Client connected from', addr)
        try:
            request = cl.recv(1024)
            debug_print("Received request:", request)
            response = handle_request(request)
            debug_print("Sending response:", response[:100] + "..." if len(response) > 100 else response)
            cl.send(response)
        except OSError as e:
            if e.errno == 104:  # Connection reset by peer
                debug_print("Connection reset by peer")
            else:
                debug_print(f"OSError in client handling: {str(e)}")
        finally:
            cl.close()
    except Exception as e:
        debug_print(f"Error in main loop: {str(e)}")
        time.sleep(1)  # Add a small delay to avoid rapid retries in case of persistent errors

How To Get OpenAI and WeatherAI API Keys:

My Wiring diagram (did not plug in the humidity sensor, but added the option in the code if you want to use it)

(it’s literally just plugged into my computer)