diff --git a/adafruit_wiznet5k/adafruit_wiznet5k.py b/adafruit_wiznet5k/adafruit_wiznet5k.py index db71c7c..cde6eac 100755 --- a/adafruit_wiznet5k/adafruit_wiznet5k.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k.py @@ -142,8 +142,10 @@ class WIZNET5K: # pylint: disable=too-many-public-methods :param ~busio.SPI spi_bus: The SPI bus the Wiznet module is connected to. :param ~digitalio.DigitalInOut cs: Chip select pin. :param ~digitalio.DigitalInOut rst: Optional reset pin. - :param bool dhcp: Whether to start DHCP automatically or not. - :param str mac: The Wiznet's MAC Address. + :param bool is_dhcp: Whether to start DHCP automatically or not. + :param list mac: The Wiznet's MAC Address. + :param str hostname: The desired hostname, with optional {} to fill in MAC. + :param int dhcp_timeout: Timeout in seconds for DHCP response. :param bool debug: Enable debugging output. """ @@ -154,7 +156,15 @@ class WIZNET5K: # pylint: disable=too-many-public-methods # pylint: disable=too-many-arguments def __init__( - self, spi_bus, cs, reset=None, is_dhcp=True, mac=DEFAULT_MAC, debug=False + self, + spi_bus, + cs, + reset=None, + is_dhcp=True, + mac=DEFAULT_MAC, + hostname=None, + dhcp_timeout=3, + debug=False, ): self._debug = debug self._chip_type = None @@ -182,13 +192,14 @@ def __init__( self._dns = 0 # Set DHCP if is_dhcp: - ret = self.set_dhcp() + ret = self.set_dhcp(hostname, dhcp_timeout) assert ret == 0, "Failed to configure DHCP Server!" - def set_dhcp(self, response_timeout=1): + def set_dhcp(self, hostname=None, response_timeout=3): """Initializes the DHCP client and attempts to retrieve and set network configuration from the DHCP server. Returns True if DHCP configured, False otherwise. + :param str hostname: The desired hostname, with optional {} to fill in MAC. :param int response_timeout: Time to wait for server to return packet, in seconds. """ @@ -197,7 +208,7 @@ def set_dhcp(self, response_timeout=1): self._src_port = 68 # Return IP assigned by DHCP _dhcp_client = dhcp.DHCP( - self, self.mac_address, response_timeout, debug=self._debug + self, self.mac_address, hostname, response_timeout, debug=self._debug ) ret = _dhcp_client.request_dhcp_lease() if ret == 1: diff --git a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py index a52d4d1..420cde2 100755 --- a/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py +++ b/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py @@ -95,23 +95,24 @@ class DHCP: """W5k DHCP Client implementation. :param eth: Wiznet 5k object :param list mac_address: Hardware MAC. - :param int timeout: Packet parsing timeout. - :param int timeout_response: DHCP Response timeout. + :param str hostname: The desired hostname, with optional {} to fill in MAC. + :param int response_timeout: DHCP Response timeout. :param bool debug: Enable debugging output. """ # pylint: disable=too-many-arguments, too-many-instance-attributes, invalid-name - def __init__(self, eth, mac_address, timeout=1, timeout_response=1, debug=False): + def __init__( + self, eth, mac_address, hostname=None, response_timeout=3, debug=False + ): self._debug = debug - self._timeout = timeout - self._response_timeout = timeout_response + self._response_timeout = response_timeout self._mac_address = mac_address # Initalize a new UDP socket for DHCP socket.set_interface(eth) self._sock = socket.socket(type=socket.SOCK_DGRAM) - self._sock.settimeout(timeout) + self._sock.settimeout(response_timeout) # DHCP state machine self._dhcp_state = STATE_DHCP_START @@ -124,6 +125,7 @@ def __init__(self, eth, mac_address, timeout=1, timeout_response=1, debug=False) self.gateway_ip = 0 self.subnet_mask = 0 self.dns_server_ip = 0 + # Lease configuration self._lease_time = 0 self._last_check_lease_ms = 0 @@ -132,6 +134,12 @@ def __init__(self, eth, mac_address, timeout=1, timeout_response=1, debug=False) self._t1 = 0 self._t2 = 0 + # Host name + mac_string = "".join("{:02X}".format(o) for o in mac_address) + self._hostname = bytes( + (hostname or "WIZnet{}").split(".")[0].format(mac_string)[:42], "utf-8" + ) + def send_dhcp_message(self, state, time_elapsed): """Assemble and send a DHCP message packet to a socket. :param int state: DHCP Message state. @@ -193,38 +201,37 @@ def send_dhcp_message(self, state, time_elapsed): # Option - Host Name _BUFF[252] = 12 - _BUFF[253] = len(b"Wiznet") + 6 - _BUFF[254:260] = b"WIZnet" - - for mac in range(0, 5): - _BUFF[260 + mac] = self._mac_address[mac] + hostname_len = len(self._hostname) + after_hostname = 254 + hostname_len + _BUFF[253] = hostname_len + _BUFF[254:after_hostname] = self._hostname if state == DHCP_REQUEST: # Set the parsed local IP addr - _BUFF[266] = 50 - _BUFF[267] = 0x04 + _BUFF[after_hostname] = 50 + _BUFF[after_hostname + 1] = 0x04 - _BUFF[268:272] = self.local_ip + _BUFF[after_hostname + 2 : after_hostname + 6] = self.local_ip # Set the parsed dhcp server ip addr - _BUFF[272] = 54 - _BUFF[273] = 0x04 - _BUFF[274:278] = self.dhcp_server_ip + _BUFF[after_hostname + 6] = 54 + _BUFF[after_hostname + 7] = 0x04 + _BUFF[after_hostname + 8 : after_hostname + 12] = self.dhcp_server_ip - _BUFF[278] = 55 - _BUFF[279] = 0x06 + _BUFF[after_hostname + 12] = 55 + _BUFF[after_hostname + 13] = 0x06 # subnet mask - _BUFF[280] = 1 + _BUFF[after_hostname + 14] = 1 # routers on subnet - _BUFF[281] = 3 + _BUFF[after_hostname + 15] = 3 # DNS - _BUFF[282] = 6 + _BUFF[after_hostname + 16] = 6 # domain name - _BUFF[283] = 15 + _BUFF[after_hostname + 17] = 15 # renewal (T1) value - _BUFF[284] = 58 + _BUFF[after_hostname + 18] = 58 # rebinding (T2) value - _BUFF[285] = 59 - _BUFF[286] = 255 + _BUFF[after_hostname + 19] = 59 + _BUFF[after_hostname + 20] = 255 # Send DHCP packet self._sock.send(_BUFF) @@ -373,7 +380,7 @@ def request_dhcp_lease( elif self._dhcp_state == STATE_DHCP_DISCOVER: if self._debug: print("* DHCP: Parsing OFFER") - msg_type, xid = self.parse_dhcp_response(self._timeout) + msg_type, xid = self.parse_dhcp_response(self._response_timeout) if msg_type == DHCP_OFFER: # use the _transaction_id the offer returned, # rather than the current one @@ -389,7 +396,7 @@ def request_dhcp_lease( elif STATE_DHCP_REQUEST: if self._debug: print("* DHCP: Parsing ACK") - msg_type, xid = self.parse_dhcp_response(self._timeout) + msg_type, xid = self.parse_dhcp_response(self._response_timeout) if msg_type == DHCP_ACK: self._dhcp_state = STATE_DHCP_LEASED result = 1 @@ -412,7 +419,9 @@ def request_dhcp_lease( msg_type = 0 self._dhcp_state = STATE_DHCP_START - if result != 1 and ((time.monotonic() - start_time > self._timeout)): + if result != 1 and ( + (time.monotonic() - start_time > self._response_timeout) + ): break self._transaction_id += 1 diff --git a/docs/conf.py b/docs/conf.py index e36a5e4..ff71ae2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -147,7 +147,7 @@ "AdafruitWiznet5k Library Documentation", author, "manual", - ), + ) ] # -- Options for manual page output --------------------------------------- @@ -178,5 +178,5 @@ "AdafruitWiznet5kLibrary", "One line description of project.", "Miscellaneous", - ), + ) ]