pythonsocketspython-requestsmicropythonraspberry-pi-pico

Raspberry Pi Pico W, Websockets and obtaining data from it


If you follow the code that the Raspberry Pi foundation provides as a sample (here) to getting started with WLAN and Sockets on Pi Pico W, is there a way for another python project to get the information that is being updated in the socket?

Code would look something like this (based on the link above) This would be on the pi pico W:

def connect():
    #Connect to WLAN
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    wlan.connect(ssid, password)
    while wlan.isconnected() == False:
        print('Waiting for connection...')
        sleep(1)
    ip = wlan.ifconfig()[0]
    print(f'Connected on {ip}')
    return ip

def open_socket(ip):
    # Open a socket
    address = (ip, 80)
    connection = socket.socket()
    connection.bind(address)
    connection.listen(1)
    return connection

def webpage(temperature, state):
    #Template HTML
    html = f"""
            <!DOCTYPE html>
            <html>
            <form action="./lighton">
            <input type="submit" value="Light on" />
            </form>
            <form action="./lightoff">
            <input type="submit" value="Light off" />
            </form>
            <p>LED is {state}</p>
            <p>Temperature is {temperature}</p>
            </body>
            </html>
            """
    return str(html)

def serve(connection):
    #Start a web server
    state = 'OFF'
    pico_led.off()
    temperature = 0
    while True:
        client = connection.accept()[0]
        request = client.recv(1024)
        request = str(request)
        try:
            request = request.split()[1]
        except IndexError:
            pass
        if request == '/lighton?':
            pico_led.on()
            state = 'ON'
        elif request =='/lightoff?':
            pico_led.off()
            state = 'OFF'
        temperature = pico_temp_sensor.temp
        html = webpage(temperature, state)
        client.send(html)
        client.close()
try:
    ip = connect()
    connection = open_socket(ip)
except KeyboardInterrupt:
    machine.reset()

This example works to get a webpage that from a browser I can navigate to with the IP address of the pi, and change the state of the onboard LED, as well as see the LED state and temperature. So let's assume that in this example, my goal is to be able to have another computer running a different python script to occasionally send a request to retrieve the state and temperature variables. Is this possible with a socket set up in this way?

I've tried using requests.get with the IP as the url, and I retrieve bad status codes with everything I've tried. I've also tried sending requests.post with the information from the Pi Pico W and that didn't give me any results either. I tried this example below, as it works for another Raspberry Pi Zero project that I have running a websocket.

import requests
import json
import time 


url = #PICO's IP, I've tried just the address, I've tried http://xxx.xxx.xxx.xxx and all end with the same error.  
while True:
    state = requests.get(url)
    #state = state.json() didn't make a difference either way, requests.get fails.
    print(state)
    time.sleep(3)

The response of this is:

requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine('\n'))

I tried putting requests.get(url) in a try and except connection error block, but it still fails with the same error after multiple attempts. I'm mostly just wondering if what I'm trying to do is even possible with the type of socket, or the configuration or something. I've tried multiple options and just cant seem to get anything back from the IP through a python script, but have no issues getting it from a browser.


Solution

  • You need to send a header with or before your response html.

    client.send("HTTP/1.0 200 OK\r\n\r\n")
    client.send(html)
    client.close()