-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Description
Today I tested the new Raspberry Pico W board and especially the network connectivity. I am aware that every version for that board is marked as "unstable" but I still wanted to Issue a report, because it is a very strange error and I couldn't find any resource on the Internet describing similar issues.
My initial plan was to implement a small IoT service with the Pico W. It should connect to a server with a valid SSL/TLS certificate via TLS1.2, send info about the current power state and also receive commands.
Here is my code for the pico w:
from machine import Pin
import network
import socket
import json
import time
import ubinascii
import sys
import os
import ussl
import _thread
WIFI_SSID = "PLACEHOLDER"
WIFI_PASSWORD = "PLACEHOLDER"
ID = "PLACEHOLDER"
SERVER_HOSTNAME = "PLACEHOLDER_HOSTNAME"
SERVER_PORT = 4001
ca_data_base64 = "PLACEHOLDER_CA_CERT_DER_BASE64"
ca_data = ubinascii.a2b_base64(ca_data_base64.encode("utf-8"))
outp = Pin(16, Pin.OUT)
inp = Pin(17, Pin.IN, Pin.PULL_DOWN)
led = Pin("LED", Pin.OUT)
server_led = Pin(15, Pin.OUT)
wifi_led = Pin(14, Pin.OUT)
def getData():
d = {"power": False}
if inp.value() == 1:
d["power"] = True
return d
def init_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.config(pm = 0xa11140)
return wlan
def connect_to_wifi(wlan):
wlan.connect(WIFI_SSID, WIFI_PASSWORD)
while not wlan.isconnected():
if wlan.status() == network.STAT_IDLE:
print("Error while Connecting to Wifi: STAT_IDLE")
elif wlan.status() == network.STAT_CONNECTING:
print("Connecting to Wifi... STAT_CONNECTING")
elif wlan.status() == network.STAT_NO_AP_FOUND:
print("Error while Connecting to Wifi: STAT_NO_AP_FOUND")
elif wlan.status() == network.STAT_CONNECT_FAIL:
print("Error while Connecting to Wifi: STAT_CONNECT_FAIL")
elif wlan.status() == network.STAT_GOT_IP:
print("Error while Connecting to Wifi: STAT_GOT_IP")
else:
print(f"Connecting to Wifi...")
print("Status: " + str(wlan.status()))
if wlan.status() < 0:
raise OSError("Wifi not connected!")
time.sleep(1)
print("Wifi Connection stable")
wifi_led.value(1)
def connect_to_server():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Connecting to server...")
s.connect(socket.getaddrinfo(SERVER_HOSTNAME, SERVER_PORT)[0][-1])
tls_socket = ussl.wrap_socket(s, server_side=False, cert_reqs=ussl.CERT_REQUIRED, cadata=ca_data, server_hostname=SERVER_HOSTNAME, do_handshake=True)
tls_socket.setblocking(False)
tls_socket.write(bytes(ID, "utf-8"))
server_led.value(1)
print("Connection to server successful")
return tls_socket
def receiving_loop(s):
while True:
try:
re = s.read(512)
if re != None:
string = re.decode("utf-8")
obj = json.loads(string)
if obj["power"]:
print("Receiving 1")
outp.value(1)
else:
print("Receiving 0")
outp.value(0)
except ValueError:
print("Error while decoding json")
def sending_loop(s):
global confirm
while True:
data = getData()
s.write(bytes(json.dumps(data), "utf-8"))
print(f"Sent {json.dumps(data)}")
time.sleep(1)
outp.value(0)
server_led.value(0)
wifi_led.value(0)
led.value(0)
time.sleep(0.3)
led.value(1)
wlan= init_wifi()
time.sleep(3)
try:
connect_to_wifi(wlan)
s = connect_to_server()
_thread.start_new_thread(receiving_loop, [s])
sending_loop(s)
except KeyboardInterrupt:
print("Interrupting")
except OSError as e:
print(e)
After implementing the backend and writing the pico w script in Thonny everything worked perfectly fine. The CA certificate I hardcoded into the software got accepted and a valid TLS connection could be established. I saved the script as main.py on the pico's flash and triple checked that it actually gets run at startup. I disconnected the pico from my Pc and plugged it into my wall adapter. I waited and I realized the pico wouldn't connect to the server at all. I checked the logs (the server is written in Java) and got "Received fatal alert: certificate_unknown" as the error message on server side. The next thing I did was to connect the pico back to my Pc and watching the execution from another COM reader other than Thonny. It still didn't work as expected with the same error on server side and the error (-9984, 'MBEDTLS_ERR_X509_CERT_VERIFY_FAILED') printed by the Pico.
When I run the script from Thonny I get this output:
Wifi Connection stable
Connecting to server...
Connection to server successful
Sent {"power": false}
Sent {"power": false}
Sent {"power": false}
[...]
When it starts by itself this is the output:
Connecting to Wifi... STAT_CONNECTING
Connecting to Wifi... STAT_CONNECTING
Connecting to Wifi... STAT_CONNECTING
Connecting to Wifi... STAT_CONNECTING
Wifi Connection stable
Connecting to server...
(-9984, 'MBEDTLS_ERR_X509_CERT_VERIFY_FAILED')
When started over and over by another script this is the output:
Connecting to Wifi... STAT_CONNECTING
Connecting to Wifi... STAT_CONNECTING
Connecting to Wifi... STAT_CONNECTING
Connecting to Wifi... STAT_CONNECTING
Wifi Connection stable
Connecting to server...
(-9984, 'MBEDTLS_ERR_X509_CERT_VERIFY_FAILED')
Wifi Connection stable
Connecting to server...
(-9984, 'MBEDTLS_ERR_X509_CERT_VERIFY_FAILED')
[...]
First I thought this might happen because Thonny restarts scripts by performing a soft-reset and to reset it normally I would cut the power which is not just a soft reset. Therefore, I implemented a soft reset with sys.exit() when the error happens. But this didn't work either. This documentation is clear about that sys.exit() should perform a soft reset, the same reset I wanted to implement but it just doesn't reset. It just exits to the normal python shell and doesn't restart main.py or boot.py. And even when I do a machine reset and the pico is somehow connected to Thonny it does work. So I assume it is not the machine reset that causes the problem but I am not entirely sure.
After 8 hours of trial and error, I can say most certainly that the Pico W would only establish a valid connection to the server when the program is run or reset by the Thonny IDE. I have no idea why that happens, or how I can solve the problem and I would really appreciate help.
The firmware is rp2-pico-w-20220815-unstable-v1.19.1-284-ga16a330da.uf2