adafruit / Adafruit_CircuitPython_Requests

Requests-like interface for web interfacing
MIT License
51 stars 37 forks source link

possible CPython incompatibility #10

Closed jerryneedell closed 5 years ago

jerryneedell commented 5 years ago

Just for fun , I tried hooking an airlift breakout to a Raspberry Pi Zero.

I then tried running the esp32spi_simpletest.py and ran into an error in requests.

Note -- I realize requests has not be released to PyPI -- I just put adafruit_requests.py in the local folder for this test.

The Aiflift seems to be working fine but the error seems to be a potential Cpython incompatibility in adafruit_requests.

I just wanted to post this for information while I experiment with it.

Not sure if anyone would really want to use an Airlift on an RPi since WiFi Dongles are less expensive, but I thought it worth demonstrating that it could be done....

pi@gjnpiairlift:~/projects/blinka/airlift $ python3 airlift.py
ESP32 SPI webclient test
ESP32 found and in idle mode
Firmware vers. bytearray(b'1.2.2\x00')
MAC addr: ['0x39', '0xa1', '0xe', '0x33', '0x4f', '0xc4']
    Needell Airport     RSSI: -37
    Needell Airport     RSSI: -64
    Needell Airport     RSSI: -70
    xfinitywifi     RSSI: -83
    Needell Airport     RSSI: -85
Connecting to AP...
could not connect to AP, retrying:  ('No such ssid', b'Needell Airport')
Connected to Needell Airport    RSSI: -37
My IP address is 10.0.0.29
IP lookup adafruit.com: 104.20.39.240
Ping google.com: 40 ms
Fetching text from http://wifitest.adafruit.com/testwifi/index.html
Traceback (most recent call last):
  File "airlift.py", line 51, in <module>
    r = requests.get(TEXT_URL)
  File "/home/pi/projects/blinka/airlift/adafruit_requests.py", line 270, in get
    return request("GET", url, **kw)
  File "/home/pi/projects/blinka/airlift/adafruit_requests.py", line 195, in request
    sock.send(b"%s /%s HTTP/1.0\r\n" % (method, path))
TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'
pi@gjnpiairlift:~/projects/blinka/airlift $ 

here is the test code -- essentially esp32spi_simpletest.py

import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests

print("ESP32 SPI webclient test")

TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html"
JSON_URL = "http://api.coindesk.com/v1/bpi/currentprice/USD.json"

# If you are using a board with pre-defined ESP32 Pins:
#esp32_cs = DigitalInOut(board.ESP_CS)
#esp32_ready = DigitalInOut(board.ESP_BUSY)
#esp32_reset = DigitalInOut(board.ESP_RESET)

# If you have an externally connected ESP32:
esp32_cs = DigitalInOut(board.D17)
esp32_ready = DigitalInOut(board.D27)
esp32_reset = DigitalInOut(board.D22)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

requests.set_socket(socket, esp)

if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
print("MAC addr:", [hex(i) for i in esp.MAC_address])

for ap in esp.scan_networks():
    print("\t%s\t\tRSSI: %d" % (str(ap['ssid'], 'utf-8'), ap['rssi']))

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(b'MYSSID', b'MYPASSWORD')
    except RuntimeError as e:
        print("could not connect to AP, retrying: ",e)
        continue
print("Connected to", str(esp.ssid, 'utf-8'), "\tRSSI:", esp.rssi)
print("My IP address is", esp.pretty_ip(esp.ip_address))
print("IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")))
print("Ping google.com: %d ms" % esp.ping("google.com"))

#esp._debug = True
print("Fetching text from", TEXT_URL)
r = requests.get(TEXT_URL)
print('-'*40)
print(r.text)
print('-'*40)
r.close()

print()
print("Fetching json from", JSON_URL)
r = requests.get(JSON_URL)
print('-'*40)
print(r.json())
print('-'*40)
r.close()

print("Done!")
jerryneedell commented 5 years ago

this minor change to adafruit_request.py seems to work both on the RPi and on a metro_m4_airlift. I'll do a bit more testing before submitting a PR.

$ diff adafruit_requests.py ../Adafruit_CircuitPython_Requests/adafruit_requests.py 
195c195
<         sock.send(b"%s /%s HTTP/1.0\r\n" % (bytes(method,"UTF-8"), bytes(path,"UTF-8")))
---
>         sock.send(b"%s /%s HTTP/1.0\r\n" % (method, path))
197c197
<             sock.send(b"Host: %s\r\n" % bytes(host,"UTF-8"))
---
>             sock.send(b"Host: %s\r\n" % host)

successful run on RPi

pi@gjnpiairlift:~/projects/blinka/airlift $ python3 airlift.py
ESP32 SPI webclient test
ESP32 found and in idle mode
Firmware vers. bytearray(b'1.2.2\x00')
MAC addr: ['0x39', '0xa1', '0xe', '0x33', '0x4f', '0xc4']
    Needell Airport     RSSI: -47
    Needell Airport     RSSI: -65
    Needell Airport     RSSI: -69
    Needell Airport     RSSI: -80
    xfinitywifi     RSSI: -81
Connecting to AP...
could not connect to AP, retrying:  ('No such ssid', b'Needell Airport')
Connected to Needell Airport    RSSI: -44
My IP address is 10.0.0.29
IP lookup adafruit.com: 104.20.39.240
Ping google.com: 40 ms
Fetching text from http://wifitest.adafruit.com/testwifi/index.html
----------------------------------------
This is a test of Adafruit WiFi!
If you can read this, its working :)

----------------------------------------

Fetching json from http://api.coindesk.com/v1/bpi/currentprice/USD.json
----------------------------------------
{'time': {'updated': 'Sep 7, 2019 11:32:00 UTC', 'updatedISO': '2019-09-07T11:32:00+00:00', 'updateduk': 'Sep 7, 2019 at 12:32 BST'}, 'disclaimer': 'This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org', 'bpi': {'USD': {'code': 'USD', 'rate': '10,396.5150', 'description': 'United States Dollar', 'rate_float': 10396.515}}}
----------------------------------------
Done!
amotl commented 4 years ago

Hi there,

thank you for caring about compatibility with CPython.

We just ran into the same issue when still using the original urequests module while trying to implement a CPython-based test harness for our Terkin Datalogger.

TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'str'

So, we are considering to switch over to the adafruit_requests module instead.

With kind regards, Andreas.