mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 23:21:54 +00:00 
			
		
		
		
	[network] Eliminate runtime string parsing for IP address initialization (#11561)
This commit is contained in:
		| @@ -14,7 +14,7 @@ from esphome.components.esp32.const import ( | |||||||
|     VARIANT_ESP32S2, |     VARIANT_ESP32S2, | ||||||
|     VARIANT_ESP32S3, |     VARIANT_ESP32S3, | ||||||
| ) | ) | ||||||
| from esphome.components.network import IPAddress | from esphome.components.network import ip_address_literal | ||||||
| from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface | from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
| @@ -320,11 +320,11 @@ def _final_validate_spi(config): | |||||||
| def manual_ip(config): | def manual_ip(config): | ||||||
|     return cg.StructInitializer( |     return cg.StructInitializer( | ||||||
|         ManualIP, |         ManualIP, | ||||||
|         ("static_ip", IPAddress(str(config[CONF_STATIC_IP]))), |         ("static_ip", ip_address_literal(config[CONF_STATIC_IP])), | ||||||
|         ("gateway", IPAddress(str(config[CONF_GATEWAY]))), |         ("gateway", ip_address_literal(config[CONF_GATEWAY])), | ||||||
|         ("subnet", IPAddress(str(config[CONF_SUBNET]))), |         ("subnet", ip_address_literal(config[CONF_SUBNET])), | ||||||
|         ("dns1", IPAddress(str(config[CONF_DNS1]))), |         ("dns1", ip_address_literal(config[CONF_DNS1])), | ||||||
|         ("dns2", IPAddress(str(config[CONF_DNS2]))), |         ("dns2", ip_address_literal(config[CONF_DNS2])), | ||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,3 +1,5 @@ | |||||||
|  | import ipaddress | ||||||
|  |  | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option | from esphome.components.esp32 import add_idf_sdkconfig_option | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| @@ -10,6 +12,41 @@ AUTO_LOAD = ["mdns"] | |||||||
| network_ns = cg.esphome_ns.namespace("network") | network_ns = cg.esphome_ns.namespace("network") | ||||||
| IPAddress = network_ns.class_("IPAddress") | IPAddress = network_ns.class_("IPAddress") | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def ip_address_literal(ip: str | int | None) -> cg.MockObj: | ||||||
|  |     """Generate an IPAddress with compile-time initialization instead of runtime parsing. | ||||||
|  |  | ||||||
|  |     This function parses the IP address in Python during code generation and generates | ||||||
|  |     a call to the 4-octet constructor (IPAddress(192, 168, 1, 1)) instead of the | ||||||
|  |     string constructor (IPAddress("192.168.1.1")). This eliminates runtime string | ||||||
|  |     parsing overhead and reduces flash usage on embedded systems. | ||||||
|  |  | ||||||
|  |     Args: | ||||||
|  |         ip: IP address as string (e.g., "192.168.1.1"), ipaddress.IPv4Address, or None | ||||||
|  |  | ||||||
|  |     Returns: | ||||||
|  |         IPAddress expression that uses 4-octet constructor for efficiency | ||||||
|  |     """ | ||||||
|  |     if ip is None: | ||||||
|  |         return IPAddress(0, 0, 0, 0) | ||||||
|  |  | ||||||
|  |     try: | ||||||
|  |         # Parse using Python's ipaddress module | ||||||
|  |         ip_obj = ipaddress.ip_address(ip) | ||||||
|  |     except (ValueError, TypeError): | ||||||
|  |         pass | ||||||
|  |     else: | ||||||
|  |         # Only support IPv4 for now | ||||||
|  |         if isinstance(ip_obj, ipaddress.IPv4Address): | ||||||
|  |             # Extract octets from the packed bytes representation | ||||||
|  |             octets = ip_obj.packed | ||||||
|  |             # Generate call to 4-octet constructor: IPAddress(192, 168, 1, 1) | ||||||
|  |             return IPAddress(octets[0], octets[1], octets[2], octets[3]) | ||||||
|  |  | ||||||
|  |     # Fallback to string constructor if parsing fails | ||||||
|  |     return IPAddress(str(ip)) | ||||||
|  |  | ||||||
|  |  | ||||||
| CONFIG_SCHEMA = cv.Schema( | CONFIG_SCHEMA = cv.Schema( | ||||||
|     { |     { | ||||||
|         cv.SplitDefault( |         cv.SplitDefault( | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ from esphome.automation import Condition | |||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| from esphome.components.const import CONF_USE_PSRAM | from esphome.components.const import CONF_USE_PSRAM | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant | from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant | ||||||
| from esphome.components.network import IPAddress | from esphome.components.network import ip_address_literal | ||||||
| from esphome.config_helpers import filter_source_files_from_platform | from esphome.config_helpers import filter_source_files_from_platform | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.config_validation import only_with_esp_idf | from esphome.config_validation import only_with_esp_idf | ||||||
| @@ -334,9 +334,7 @@ def eap_auth(config): | |||||||
|  |  | ||||||
|  |  | ||||||
| def safe_ip(ip): | def safe_ip(ip): | ||||||
|     if ip is None: |     return ip_address_literal(ip) | ||||||
|         return IPAddress(0, 0, 0, 0) |  | ||||||
|     return IPAddress(str(ip)) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def manual_ip(config): | def manual_ip(config): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user