Skip to content

UDP Client using socket #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 26, 2021
Merged

UDP Client using socket #127

merged 7 commits into from
Mar 26, 2021

Conversation

anecdata
Copy link
Member

UDP Client was previously possible using esp calls directly. This change allows UDP Client at the socket level.

@anecdata anecdata marked this pull request as ready for review March 18, 2021 19:51
@anecdata anecdata requested a review from a team March 18, 2021 20:21
Copy link
Contributor

@jposada202020 jposada202020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this

Adafruit CircuitPython 6.2.0-beta.2 on 2021-02-11; Raspberry Pi Pico with rp2040

Using an Airlift Module

with a little modified testing code as presented in PR #128 aca519f

Test Code

# SPDX-FileCopyrightText: 2021 Adafruit Industries
# SPDX-License-Identifier: MIT

import struct
import time
import board
from digitalio import DigitalInOut
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
import busio

# Get wifi details and more from a secrets.py file
try:
    from privados import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

TIMEOUT = 5
# edit host and port to match server
HOST = "pool.ntp.org"
PORT = 123
NTP_TO_UNIX_EPOCH = 2208988800  # 1970-01-01 00:00:00

# PyPortal or similar; edit pins as needed
esp32_cs = DigitalInOut(board.GP5)
esp32_ready = DigitalInOut(board.GP6)
esp32_reset = DigitalInOut(board.GP7)
spi = busio.SPI(board.GP2, board.GP3, board.GP4)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

# connect to wifi AP
esp.connect(secrets)

# test for connectivity to server
print("Server ping:", esp.ping(HOST), "ms")

# create the socket
socket.set_interface(esp)
socketaddr = socket.getaddrinfo(HOST, PORT)[0][4]
s = socket.socket()

s.settimeout(TIMEOUT)

print("Sending")
s.connect(socketaddr, esp.UDP_MODE)
packet = bytearray(48)
packet[0] = 0b00100011  # Not leap second, NTP version 4, Client mode
s.send(packet, esp.UDP_MODE)

print("Receiving")
packet = s.recv(48)
seconds = struct.unpack_from("!I", packet, offset=len(packet) - 8)[0]
print("Time:", time.localtime(seconds - NTP_TO_UNIX_EPOCH))

Result

Server ping: 150 ms Sending Receiving Time: struct_time(tm_year=2021, tm_mon=3, tm_mday=18, tm_hour=22, tm_min=54, tm_sec=46, tm_wday=3, tm_yday=77, tm_isdst=-1)

Looks good to me

@anecdata
Copy link
Member Author

@brentru Do you see any issues with adding the kwarg to socket.send()?

@brentru
Copy link
Member

brentru commented Mar 19, 2021

I do have an issue with this PR - the socket class should match CPython Socket send (https://docs.python.org/3.8/library/socket.html#socket.socket.send) and SocketPool's socket send (https://circuitpython.readthedocs.io/en/latest/shared-bindings/socketpool/index.html#socketpool.Socket.send).

Instead, like CPython, within the init's type kwarg, could you pass SOCK_DGRAM from the code initializing the socket, instead of SOCK_STREAM to make the socket a UDP type? The conntype kwarg wouldn't be added to send since you could add a new private type attribute to the socket.

@anecdata
Copy link
Member Author

I can look in to that. I mirrored the way connect uses the kwarg (even though there is no "connect" with UDP, the call is needed - NINA, and the Arduino WiFi structures it's written around are very un-CPython-like.).

@anecdata
Copy link
Member Author

anecdata commented Mar 19, 2021

Re-tested with (modified) UDP client. Regression tested with TCP client and HTTP client (Requests).

anecdata added a commit that referenced this pull request Mar 19, 2021
to match latest UDP client PR #127 commit
@anecdata anecdata mentioned this pull request Mar 19, 2021
@anecdata anecdata requested a review from brentru March 19, 2021 16:40
Copy link
Member

@brentru brentru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, I had to modify @jposada202020 's NTP code to reflect PR #129

# SPDX-FileCopyrightText: 2021 Adafruit Industries
# SPDX-License-Identifier: MIT

import struct
import time
import board
from digitalio import DigitalInOut
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
import busio

# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

TIMEOUT = 5
# edit host and port to match server
HOST = "pool.ntp.org"
PORT = 123
NTP_TO_UNIX_EPOCH = 2208988800  # 1970-01-01 00:00:00


# 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)


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


# connect to wifi AP
esp.connect(secrets)

# test for connectivity to server
print("Server ping:", esp.ping(HOST), "ms")

# create the socket
socket.set_interface(esp)
socketaddr = socket.getaddrinfo(HOST, PORT)[0][4]
s = socket.socket(type=socket.SOCK_DGRAM)

s.settimeout(TIMEOUT)

print("Sending")
s.connect(socketaddr, esp.UDP_MODE)
packet = bytearray(48)
packet[0] = 0b00100011  # Not leap second, NTP version 4, Client mode
s.send(packet)

print("Receiving")
packet = s.recv(48)
seconds = struct.unpack_from("!I", packet, offset=len(packet) - 8)[0]
print("Time:", time.localtime(seconds - NTP_TO_UNIX_EPOCH))

Output:

code.py output:
Server ping: 20 ms
Sending
Receiving
Time: struct_time(tm_year=2021, tm_mon=3, tm_mday=26, tm_hour=15, tm_min=27, tm_sec=45, tm_wday=4, tm_yday=85, tm_isdst=-1)

Tested on Adafruit CircuitPython 6.2.0-beta.4 on 2021-03-18; Adafruit PyPortal with samd51j20

@brentru brentru merged commit 605ff44 into adafruit:master Mar 26, 2021
@anecdata anecdata deleted the udp_client branch March 26, 2021 15:36
adafruit-adabot added a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request Mar 27, 2021
@anecdata anecdata linked an issue Sep 15, 2021 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Request to include datagram type for sockets
3 participants