From 09036f204fdac4979b52718c3246234924552631 Mon Sep 17 00:00:00 2001 From: sdfsdf Date: Sat, 23 Oct 2021 17:52:35 +0200 Subject: [PATCH 1/5] Added the ability to set static ip, set hostname, and set DNS with the esp32spi interface as the esp32SPI interface supports this --- adafruit_esp32spi/adafruit_esp32spi.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index f93a0f7..cac8b93 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -37,6 +37,9 @@ _SET_NET_CMD = const(0x10) _SET_PASSPHRASE_CMD = const(0x11) +_SET_IP_CONFIG = const(0x14) +_SET_DNS_CONFIG = const(0x15) +_SET_HOSTNAME = const(0x16) _SET_AP_NET_CMD = const(0x18) _SET_AP_PASSPHRASE_CMD = const(0x19) _SET_DEBUG_CMD = const(0x1A) @@ -405,6 +408,26 @@ def scan_networks(self): return APs return None + def set_ip_config(self, ip, gw, mask="255.255.255.0"): + """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ + resp = self._send_command_get_response(_SET_IP_CONFIG, + params= [b"\x00",self.unpretty_ip(ip),self.unpretty_ip(gw), self.unpretty_ip(mask)], + sent_param_len_16=False) + return resp + + def set_dns_config(self, dns1, dns2="8.8.8.8"): + """Tells the ESP32 to set DNS, with dns2 default to google dns=8.8.8.8""" + resp = self._send_command_get_response(_SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)]) + if resp[0][0] != 1: + raise RuntimeError("Failed to set dns with esp32") + + def set_hostname(self, hostname): + """Tells the ESP32 to set hostname""" + resp = self._send_command_get_response(_SET_HOSTNAME, [hostname]) + return resp + if resp[0][0] != 1: + raise RuntimeError("Failed to set hostname with esp32") + def wifi_set_network(self, ssid): """Tells the ESP32 to set the access point to the given ssid""" resp = self._send_command_get_response(_SET_NET_CMD, [ssid]) From 9a40af7e56d9d88587f873b7ba91dcf3cef98c48 Mon Sep 17 00:00:00 2001 From: manpowre Date: Sat, 23 Oct 2021 19:57:12 +0200 Subject: [PATCH 2/5] Update adafruit_esp32spi.py --- adafruit_esp32spi/adafruit_esp32spi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index cac8b93..aa1a854 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -408,10 +408,10 @@ def scan_networks(self): return APs return None - def set_ip_config(self, ip, gw, mask="255.255.255.0"): + def set_ip_config(self, new_ip, new_gw, new_mask="255.255.255.0"): """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ resp = self._send_command_get_response(_SET_IP_CONFIG, - params= [b"\x00",self.unpretty_ip(ip),self.unpretty_ip(gw), self.unpretty_ip(mask)], + params= [b"\x00",self.unpretty_ip(new_ip),self.unpretty_ip(new_gw), self.unpretty_ip(new_mask)], sent_param_len_16=False) return resp From e433ef675a119bf5f3cefcbde825718c2b6839b2 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Thu, 17 Mar 2022 20:28:09 +0100 Subject: [PATCH 3/5] apply black and add example --- adafruit_esp32spi/adafruit_esp32spi.py | 30 +++++++--- examples/esp32spi_ipconfig.py | 82 ++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 examples/esp32spi_ipconfig.py diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index aa1a854..c9d5ace 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -410,21 +410,35 @@ def scan_networks(self): def set_ip_config(self, new_ip, new_gw, new_mask="255.255.255.0"): """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ - resp = self._send_command_get_response(_SET_IP_CONFIG, - params= [b"\x00",self.unpretty_ip(new_ip),self.unpretty_ip(new_gw), self.unpretty_ip(new_mask)], - sent_param_len_16=False) + resp = self._send_command_get_response( + _SET_IP_CONFIG, + params=[ + b"\x00", + self.unpretty_ip(new_ip), + self.unpretty_ip(new_gw), + self.unpretty_ip(new_mask), + ], + sent_param_len_16=False, + ) return resp def set_dns_config(self, dns1, dns2="8.8.8.8"): """Tells the ESP32 to set DNS, with dns2 default to google dns=8.8.8.8""" - resp = self._send_command_get_response(_SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)]) + resp = self._send_command_get_response( + _SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)] + ) if resp[0][0] != 1: raise RuntimeError("Failed to set dns with esp32") - + def set_hostname(self, hostname): - """Tells the ESP32 to set hostname""" - resp = self._send_command_get_response(_SET_HOSTNAME, [hostname]) - return resp + """ + Tells the ESP32 to set hostname + + :params str hostname: Set the host name, used by DHCP to associate a local + domain name like hostname.home for example, depending + on the DHCP server setup. + """ + resp = self._send_command_get_response(_SET_HOSTNAME, [hostname.encode()]) if resp[0][0] != 1: raise RuntimeError("Failed to set hostname with esp32") diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py new file mode 100644 index 0000000..fceb512 --- /dev/null +++ b/examples/esp32spi_ipconfig.py @@ -0,0 +1,82 @@ +import time +import board +import busio +from digitalio import DigitalInOut +import adafruit_requests as requests +import adafruit_esp32spi.adafruit_esp32spi_socket as socket +from adafruit_esp32spi import adafruit_esp32spi +import neopixel +from rainbowio import colorwheel +import gc +from secrets import secrets + +IP_ADDRESS = "192.168.2.2" +GATEWAY_ADDRESS = "192.168.2.1" +SUBNET_MASK = "255.255.255.0" + +UDP_IN_ADDR = "192.168.2.2" +UDP_IN_PORT = 5500 + +UDP_TIMEOUT = 20 + +esp32_cs = DigitalInOut(board.CS1) +esp32_ready = DigitalInOut(board.ESP_BUSY) +esp32_reset = DigitalInOut(board.ESP_RESET) + +spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) + +esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) +socket.set_interface(esp) + +s_in = socket.socket(type=socket.SOCK_DGRAM) +s_in.settimeout(UDP_TIMEOUT) +print("set hostname:") +esp.set_hostname("new_hostname".encode("utf-8")) + +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]) + +print("Connecting to AP...") +while not esp.is_connected: + try: + esp.connect_AP(secrets["ssid"], secrets["password"]) + except RuntimeError as e: + print("could not connect to AP, retrying: ", e) + continue +print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi) +ip1 = esp.ip_address + +print("set ip dns") +esp.set_dns_config("192.168.2.1", "8.8.8.8") + +print("set ip config") +esp.set_ip_config(IP_ADDRESS, GATEWAY_ADDRESS, SUBNET_MASK) + +time.sleep(1) +ip2 = esp.ip_address + +time.sleep(1) +info = esp.network_data +print( + "get network_data: ", + esp.pretty_ip(info["ip_addr"]), + esp.pretty_ip(info["gateway"]), + esp.pretty_ip(info["netmask"]), +) + +IP_ADDR = esp.pretty_ip(esp.ip_address) +print("ip:", IP_ADDR) +print("My IP address is", esp.pretty_ip(esp.ip_address)) +print("udp in addr: ", UDP_IN_ADDR, UDP_IN_PORT) + +socketaddr_udp_in = socket.getaddrinfo(UDP_IN_ADDR, UDP_IN_PORT)[0][4] +s_in.connect(socketaddr_udp_in, conntype=esp.UDP_MODE) +print("connected local UDP") + +while True: + data = s_in.recv(1205) + if len(data) >= 1: + data = data.decode("utf-8") + print(len(data), data) From f4481be6608aa6546500f5dd55be11b3e994aea8 Mon Sep 17 00:00:00 2001 From: Neradoc Date: Thu, 17 Mar 2022 22:59:17 +0100 Subject: [PATCH 4/5] cleanup and fix comments, cleanup examples --- adafruit_esp32spi/adafruit_esp32spi.py | 53 +++++++++++++------------- adafruit_esp32spi/digitalio.py | 9 ++++- examples/esp32spi_ipconfig.py | 23 ++++++----- 3 files changed, 49 insertions(+), 36 deletions(-) diff --git a/adafruit_esp32spi/adafruit_esp32spi.py b/adafruit_esp32spi/adafruit_esp32spi.py index c9d5ace..2b113d8 100644 --- a/adafruit_esp32spi/adafruit_esp32spi.py +++ b/adafruit_esp32spi/adafruit_esp32spi.py @@ -408,22 +408,31 @@ def scan_networks(self): return APs return None - def set_ip_config(self, new_ip, new_gw, new_mask="255.255.255.0"): - """Tells the ESP32 to set ip, gateway and network mask b"\xFF" """ + def set_ip_config(self, ip_address, gateway, mask="255.255.255.0"): + """Tells the ESP32 to set ip, gateway and network mask b"\xFF" + + :param str ip_address: IP address (as a string). + :param str gateway: Gateway (as a string). + :param str mask: Mask, defaults to 255.255.255.0 (as a string). + """ resp = self._send_command_get_response( _SET_IP_CONFIG, params=[ b"\x00", - self.unpretty_ip(new_ip), - self.unpretty_ip(new_gw), - self.unpretty_ip(new_mask), + self.unpretty_ip(ip_address), + self.unpretty_ip(gateway), + self.unpretty_ip(mask), ], sent_param_len_16=False, ) return resp - def set_dns_config(self, dns1, dns2="8.8.8.8"): - """Tells the ESP32 to set DNS, with dns2 default to google dns=8.8.8.8""" + def set_dns_config(self, dns1, dns2): + """Tells the ESP32 to set DNS + + :param str dns1: DNS server 1 IP as a string. + :param str dns2: DNS server 2 IP as a string. + """ resp = self._send_command_get_response( _SET_DNS_CONFIG, [b"\x00", self.unpretty_ip(dns1), self.unpretty_ip(dns2)] ) @@ -431,12 +440,9 @@ def set_dns_config(self, dns1, dns2="8.8.8.8"): raise RuntimeError("Failed to set dns with esp32") def set_hostname(self, hostname): - """ - Tells the ESP32 to set hostname + """Tells the ESP32 to set hostname for DHCP. - :params str hostname: Set the host name, used by DHCP to associate a local - domain name like hostname.home for example, depending - on the DHCP server setup. + :param str hostname: The new host name. """ resp = self._send_command_get_response(_SET_HOSTNAME, [hostname.encode()]) if resp[0][0] != 1: @@ -555,8 +561,7 @@ def connect(self, secrets): self.connect_AP(secrets["ssid"], secrets["password"]) def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-name - """ - Connect to an access point with given name and password. + """Connect to an access point with given name and password. Will wait until specified timeout seconds and return on success or raise an exception on failure. @@ -589,8 +594,7 @@ def connect_AP(self, ssid, password, timeout_s=10): # pylint: disable=invalid-n def create_AP( self, ssid, password, channel=1, timeout=10 ): # pylint: disable=invalid-name - """ - Create an access point with the given name, password, and channel. + """Create an access point with the given name, password, and channel. Will wait until specified timeout seconds and return on success or raise an exception on failure. @@ -851,8 +855,7 @@ def set_esp_debug(self, enabled): raise RuntimeError("Failed to set debug mode") def set_pin_mode(self, pin, mode): - """ - Set the io mode for a GPIO pin. + """Set the io mode for a GPIO pin. :param int pin: ESP32 GPIO pin to set. :param value: direction for pin, digitalio.Direction or integer (0=input, 1=output). @@ -868,8 +871,7 @@ def set_pin_mode(self, pin, mode): raise RuntimeError("Failed to set pin mode") def set_digital_write(self, pin, value): - """ - Set the digital output value of pin. + """Set the digital output value of pin. :param int pin: ESP32 GPIO pin to write to. :param bool value: Value for the pin. @@ -881,8 +883,7 @@ def set_digital_write(self, pin, value): raise RuntimeError("Failed to write to pin") def set_analog_write(self, pin, analog_value): - """ - Set the analog output value of pin, using PWM. + """Set the analog output value of pin, using PWM. :param int pin: ESP32 GPIO pin to write to. :param float value: 0=off 1.0=full on @@ -895,8 +896,7 @@ def set_analog_write(self, pin, analog_value): raise RuntimeError("Failed to write to pin") def set_digital_read(self, pin): - """ - Get the digital input value of pin. Returns the boolean value of the pin. + """Get the digital input value of pin. Returns the boolean value of the pin. :param int pin: ESP32 GPIO pin to read from. """ @@ -914,8 +914,7 @@ def set_digital_read(self, pin): ) def set_analog_read(self, pin, atten=ADC_ATTEN_DB_11): - """ - Get the analog input value of pin. Returns an int between 0 and 65536. + """Get the analog input value of pin. Returns an int between 0 and 65536. :param int pin: ESP32 GPIO pin to read from. :param int atten: attenuation constant @@ -951,6 +950,7 @@ def get_time(self): def set_certificate(self, client_certificate): """Sets client certificate. Must be called BEFORE a network connection is established. + :param str client_certificate: User-provided .PEM certificate up to 1300 bytes. """ if self._debug: @@ -973,6 +973,7 @@ def set_certificate(self, client_certificate): def set_private_key(self, private_key): """Sets private key. Must be called BEFORE a network connection is established. + :param str private_key: User-provided .PEM file up to 1700 bytes. """ if self._debug: diff --git a/adafruit_esp32spi/digitalio.py b/adafruit_esp32spi/digitalio.py index d825f70..c935794 100755 --- a/adafruit_esp32spi/digitalio.py +++ b/adafruit_esp32spi/digitalio.py @@ -50,6 +50,7 @@ def __init__(self, esp_pin, esp): def init(self, mode=IN): """Initalizes a pre-defined pin. + :param mode: Pin mode (IN, OUT, LOW, HIGH). Defaults to IN. """ if mode is not None: @@ -64,6 +65,7 @@ def init(self, mode=IN): def value(self, val=None): """Sets ESP32 Pin GPIO output mode. + :param val: Pin output level (LOW, HIGH) """ if val is not None: @@ -133,6 +135,7 @@ def deinit(self): def switch_to_output(self, value=False, drive_mode=DriveMode.PUSH_PULL): """Set the drive mode and value and then switch to writing out digital values. + :param bool value: Default mode to set upon switching. :param DriveMode drive_mode: Drive mode for the output. """ @@ -142,6 +145,7 @@ def switch_to_output(self, value=False, drive_mode=DriveMode.PUSH_PULL): def switch_to_input(self, pull=None): """Sets the pull and then switch to read in digital values. + :param Pull pull: Pull configuration for the input. """ raise NotImplementedError( @@ -156,6 +160,7 @@ def direction(self): @direction.setter def direction(self, pin_dir): """Sets the direction of the pin. + :param Direction dir: Pin direction (Direction.OUTPUT or Direction.INPUT) """ self.__direction = pin_dir @@ -176,6 +181,7 @@ def value(self): @value.setter def value(self, val): """Sets the digital logic level of the pin. + :param type value: Pin logic level. :param int value: Pin logic level. 1 is logic high, 0 is logic low. :param bool value: Pin logic level. True is logic high, False is logic low. @@ -195,8 +201,9 @@ def drive_mode(self): @drive_mode.setter def drive_mode(self, mode): """Sets the pin drive mode. + :param DriveMode mode: Defines the drive mode when outputting digital values. - Either PUSH_PULL or OPEN_DRAIN + Either PUSH_PULL or OPEN_DRAIN """ if mode is DriveMode.OPEN_DRAIN: raise NotImplementedError( diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index fceb512..c72e34a 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -1,20 +1,25 @@ +# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + import time import board import busio from digitalio import DigitalInOut -import adafruit_requests as requests import adafruit_esp32spi.adafruit_esp32spi_socket as socket from adafruit_esp32spi import adafruit_esp32spi -import neopixel -from rainbowio import colorwheel -import gc -from secrets import secrets -IP_ADDRESS = "192.168.2.2" -GATEWAY_ADDRESS = "192.168.2.1" +# 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 + +IP_ADDRESS = "192.168.1.111" +GATEWAY_ADDRESS = "192.168.1.1" SUBNET_MASK = "255.255.255.0" -UDP_IN_ADDR = "192.168.2.2" +UDP_IN_ADDR = "192.168.1.1" UDP_IN_PORT = 5500 UDP_TIMEOUT = 20 @@ -49,7 +54,7 @@ ip1 = esp.ip_address print("set ip dns") -esp.set_dns_config("192.168.2.1", "8.8.8.8") +esp.set_dns_config("192.168.1.1", "8.8.8.8") print("set ip config") esp.set_ip_config(IP_ADDRESS, GATEWAY_ADDRESS, SUBNET_MASK) From ab41a20f701850693f8401c557448e4f60a9751d Mon Sep 17 00:00:00 2001 From: Neradoc Date: Fri, 18 Mar 2022 09:30:50 +0100 Subject: [PATCH 5/5] fix ipconfig example use of encode --- examples/esp32spi_ipconfig.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/esp32spi_ipconfig.py b/examples/esp32spi_ipconfig.py index c72e34a..01f01c8 100644 --- a/examples/esp32spi_ipconfig.py +++ b/examples/esp32spi_ipconfig.py @@ -15,6 +15,8 @@ print("WiFi secrets are kept in secrets.py, please add them there!") raise +HOSTNAME = "esp32-spi-hostname-test" + IP_ADDRESS = "192.168.1.111" GATEWAY_ADDRESS = "192.168.1.1" SUBNET_MASK = "255.255.255.0" @@ -35,8 +37,8 @@ s_in = socket.socket(type=socket.SOCK_DGRAM) s_in.settimeout(UDP_TIMEOUT) -print("set hostname:") -esp.set_hostname("new_hostname".encode("utf-8")) +print("set hostname:", HOSTNAME) +esp.set_hostname(HOSTNAME) if esp.status == adafruit_esp32spi.WL_IDLE_STATUS: print("ESP32 found and in idle mode")